Excel Macro Tutorial 6 – Add macro buttons to your toolbar

Author: ericains  |  Category: Computing

The finishing touch will be to put your macros into the toolbar, so they will be available to you every time you open up excel.
I have been working with Excel 2007 in these tutorials but up to this point everything I have shown you will work with 2003 and most other versions.  With 2007 Microsoft removed the ability to (without tricky tweaking) make a custom drop-down menu in Excel.  But they did make it easy to add a custom button to the quick access bar for a single macro.  For a great tutorial on adding custom menus to 2003 see this page: Assign a Macro to a Toolbar or Menu.  For 2007 see my tutorial below.


Adding a custom macro button to the Excel 2007 quick access toolbar:

The first thing to do is make sure you’ve been putting your macro code in the right place.  If you put the code in the workbook it will be available to anyone who opens that file.  But in this example we open and process a new workbook every day.  So we should put the code in our personal macro file.  This makes it available to you every time you open Excel.  Open the visual basic editor to look at your files:
bill report personal xlsb  

If you have been putting your code in a workbook, or someone shared a workbook with you with macros in it, you can simply copy and paste the code into ‘Module1’ of your PERSONAL.XLSB file. 
(Note: Don’t have a PERSONAL.XLSB?  Here are instructions on creating one: How to create a Personal.xlsb )

After making sure the code is in personal.xlsb, it is easy to add quick access buttons to your macros.
Click on the down arrow button on your quick access toolbar:
bill report more commands   
Click ‘More Commands…’
From the ‘Choose commands from’ drop-down select ‘Macros’
bill report choose commands
All of the macros in your Personal.xlsb file should be listed:
bill report macros
Now you can simply click each one and add it to your toolbar.
The toolbar ends up looking something like this:
bill report undone toolbar 
Go back to the quick access options by clicking ‘More Commands’ again.  You can change the icon for any item by selecting it and clicking the ‘Modify’ button.  Here is how my toolbar looked after modifying:
bill report after toolbar 

Well that’s it!  Now a task that took 5-10 minutes per report can be done in about 30 seconds.  What will you do with all your extra time?

Can you think of any improvements for this set of macros?

Back to tutorial 1

Download all the macros covered in this tutorial:

Here is my Personal.xlsb file containing a slightly improved version of all the macros in this tutorial: PERSONAL.XLSB

Here is an excel workbook with fake patients you can test the macros out on: FakeBillingReport.xlsx

Here is a macro-enabled excel workbook with the code in the workbook: FakeBillingReport.xlsm (macros inside) (in case you had trouble getting to the macros in PERSONAL.xlsb).

Excel Macro Tutorial 5 – Delete cancelled tests, flag credited tests

Author: ericains  |  Category: Computing

When a test is cancelled in the system it appears as a charge and then a credit with the same date and time. 
bill report dupe1
The billing team does not want to see these, as they have to charge for a test and them immediately credit a test, and it’s a hassle.  So we clean them up before submitting.
Often a test gets ordered, cancelled, and then re-ordered, so it is important to make sure the code doesn’t delete the re-ordered test:
bill report dupe2
(In this case they ordered the test then realized it was already ordered so they cancelled the new order).

There are also simple credited tests, for whatever reason we cannot charge for them.  The billing team wants’ these tests to be highlighted and the word CREDIT typed in red in the last column beside it.
bill report credit
Also on these credited tests the quantity is a positive 1.  For whatever reason, the billing team wants this changed to a negative 1.

This will be the most complicated macro so far, and since we may be fiddling with multiple rows at a time, we cannot afford to use a janky while loop that changes it’s index on the fly like our previous macros.  Instead we will make a list of the rows that need to be deleted/marked, and double check them before taking action.

First thing I will do is add a UDT (User-defined-type) to the module. This will make the code much easier to understand and work with because we will be doing a lot of scanning and checking.

How to add a UDT to an Excel macro:

Private Type DELETEDTESTS
     strPatientName As String
     dtDateTime As Date
     strTestName As String
     intRow As Integer
End Type

Dim TestsToDelete() As DELETEDTESTS

Dim TestsToFlag() As DELETEDTESTS

You have to put UDT’s in a module, at the top of the module:

bill report udt place

I named the function HandleCredits. It uses 2 other functions called "SeekEvilTwin" and "IsInTestsToBeDeletedAlready". You have to read the comments in the code to understand why these are so interestingly named.

Advanced Excel macro example with arrays, UDT’s, and functions:

Sub HandleCredits()
    'This macro will seek credits and take the appropriate action to handle them.
    'Cancelled tests will cancel each other out and be deleted.
    'Single credited tests will be highlighted and have quantity changed to a negative.

    'For this macro we could use a nested loop, but for clarity we will put the second
    'loop inside a separate function.
    'To record which row, patient, and time need to be deleted we will use an array and
    'a UDT or user-defined-type.  A separate array will handle simple credits.
    'The UDT is defined at the top of the macro module, along with the UDT arrays:
    'TestsToDelete() and TestsToFlag()

    'Loop through and analyze entire report
    intFinalRow = Range("A65536").End(xlUp).Row
    Dim intX As Integer 'Index to keep track in loop.
    ReDim TestsToDelete(0 To 0) 'This prepares the array and makes one blank spot ready.
    ReDim TestsToFlag(0 To 0)

    'This is a For Next loop and will repeat a fixed number of times unless 'Exit For' is read.
    For intX = 2 To intFinalRow 'For each row in the report...
        'We only care about credits so if the charge is positive we skip it.
        If Cells(intX, 5).Value < 0 Then 'If negative value then check.
            'Ok now we need to figure out if it's a credit or a cancel.  How?
            'Cancelled tests have an 'Evil Twin', a test with same Patient Name, Test, and DATE/TIME, but a positive charge. (why is positive evil? Because we can't overcharge!)
            'Credited tests may have a test with only the same Name and Test, but the DATE/TIME will be different.  More like an 'Evil Cousin". We don't care about them.
            'I will make a function to search for an evil twin, if none is found, the test will be added to the TestsToFlag array.

            Dim EvilTwinTest As DELETEDTESTS 'Stores evil twin info if found.
            Dim CreditedTest As DELETEDTESTS 'We can use the UDT to store test info, and pass it to our evil twin seeking function.
            With CreditedTest
                .strPatientName = Cells(intX, 1).Value
                .strTestName = Cells(intX, 3).Value
                .dtDateTime = Cells(intX, 8).Value
                .intRow = intX
            End With

            EvilTwinTest = SeekEvilTwin(CreditedTest) 'Seek it's twin!

            If EvilTwinTest.intRow > 0 Then 'This is a cancel
                'A test with same Patient name, date/time, but positive charge was found. This is a cancelled test.
                'Now we add this test and it's twin to the TestsToDelete array, to be deleted later.
                If UBound(TestsToDelete) = 0 Then 'Initially we set it to 0, so our blank spot is ready.
                    TestsToDelete(0) = CreditedTest

                    ReDim Preserve TestsToDelete(0 To 1)   'Have to make a spot for it's evil twin while preserving first info
                    TestsToDelete(1) = EvilTwinTest

                Else 'Increase array size and populate accordingly.
                    ReDim Preserve TestsToDelete(LBound(TestsToDelete) To UBound(TestsToDelete) + 1)
                    TestsToDelete(UBound(TestsToDelete)) = CreditedTest

                    ReDim Preserve TestsToDelete(LBound(TestsToDelete) To UBound(TestsToDelete) + 1)
                    TestsToDelete(UBound(TestsToDelete)) = EvilTwinTest
                End If 'End check for beginning of array.

            Else 'nothing indicates not found, so this is a credit.
                'Add test to TestsToFlag array
                If TestsToFlag(UBound(TestsToFlag)).strPatientName = "" Then 'Initially we set it to 0, so our blank spot is ready.
                    TestsToFlag(0) = CreditedTest

                Else 'Increase array size and populate accordingly.
                    ReDim Preserve TestsToFlag(LBound(TestsToFlag) To UBound(TestsToFlag) + 1)
                    TestsToFlag(UBound(TestsToFlag)) = CreditedTest
                End If 'End check for beginning of array.
            End If 'End check for evil twin (cancelled test)

        Else 'Else skip to next.
        End If 'End check neg val if.
    Next intX 'On to the next record

    'The loop has scanned the sheet and given us two arrays TestsToDelete and TestsToFlag.
    'Handling TestsToDelete may alter the row numbers of the data on the sheet, so we will start with TestsToFlag
    Dim intZ As Integer
    For intZ = LBound(TestsToFlag) To UBound(TestsToFlag)
        With TestsToFlag(intZ)
            'Remember, there will be at least one slot in TestsToFlag even if none matched, so we check for that:
            If .intRow > 0 And .strPatientName <> "" Then 'Something is there.
                'Add the credit flag and highlighting.
                Cells(.intRow, 9).Interior.Color = vbYellow
                Cells(.intRow, 9).Font.Color = vbRed
                Cells(.intRow, 9).Value = "CREDIT"

                'Remember we need to change that quantity value in other column.
                Cells(.intRow, 6).Value = -1 'Change value from 1 to -1.
            End If 'End check for blank.
        End With
    Next intZ

    'All done with TestsToFlag, we should delete it to make sure it doesn't end up getting used on another worksheet somehow.
    Erase TestsToFlag

    'Now we can handle TestsToDelete. We have to be careful, if we delete a row at the top of the sheet, all the indexes
    'of the other rows will be off by one and so on.
    'Two ways we might manage this: 1-Instead of deleting rows, just blank them out, then use the DeleteZero macro we made earlier to clean up.
                                   '2-Instead on starting at the top we can start at the bottom and work our way up.
    'The problem with just working back up is that the rows in TestsToDelete might not be in perfectly sequential order.
    'So the safest bet is to just blank out the unwanted rows and delete all blank rows afterward.
    'Still just for the examples sake I will loop through the array in reverse so you can see how that is done.

    Dim intW As Integer
    For intW = UBound(TestsToDelete) To LBound(TestsToDelete) Step -1
        With TestsToDelete(intW)
            If .intRow > 0 And .strPatientName <> "" Then 'Something is there.
                'We know what row to delete so we could just do that here, but since this is a medical/financial macro, we'll add an extra check
                'to be sure we're deleting the right thing.
                'It is unsafe to do a direct comparison of DATE/TIME's.  So I use CDate to convert the raw cell value to a date/time.
                If Cells(.intRow, 1).Value = .strPatientName And Cells(.intRow, 3).Value = .strTestName And CDate(Cells(.intRow, 8).Value) = .dtDateTime Then
                    'Everything matches up, delete it.
                    Rows(.intRow).Clear

                Else 'Uh-oh something is wrong
                    'Alert the user and abort before you mess anything else up.
                    MsgBox "Macro tried to delete wrong row? Aborting.", vbCritical, "Macro error in HandleCredits"
                    Exit Sub
                End If 'End verify row information
            End If 'end check for blank.
        End With '(TestsToDelete)

    Next intW 'Next

    'All done, erase TestsToDelete
    Erase TestsToDelete

    'Delete blank rows
    DeleteZero

End Sub

Function SeekEvilTwin(CreditedTest As DELETEDTESTS) As DELETEDTESTS
    'This will loop through all the rows again seeking the twin.
    'If the user has run the macros in order the sort has already been performed,
    'and the original charge will be above the credited row we are working on.
    'But since we can't be sure the sort has been done we check all rows.

    intFinalRow = Range("A65536").End(xlUp).Row
    Dim intY As Integer 'Index to keep track in loop.

    'This is a For Next loop and will repeat a fixed number of times unless 'Exit For' is read.
    For intY = 2 To intFinalRow 'For each row in the report...
        If Cells(intY, 5).Value > 0 Then 'Looking for the twin with positive charge. (this will also keep us from comparing the same line to itself)
            'Compare the current row info to what we were given.
            Dim CurrentTest As DELETEDTESTS
            With CurrentTest
                .strPatientName = Cells(intY, 1).Value
                .strTestName = Cells(intY, 3).Value
                .dtDateTime = Cells(intY, 8).Value
                .intRow = intY
            End With

            'Can we compare the udt directly? A: No, because row will be different.
            With CurrentTest
                If .strPatientName = CreditedTest.strPatientName And .strTestName = CreditedTest.strTestName Then
                    'Aha! They match, but is it an evil twin or an evil cousin?
                    If .dtDateTime = CreditedTest.dtDateTime Then 'Evil twin it is
                        'We are still not done checking, multiple charge/credit pairs with the same date and time
                        'can exist, so we must make sure this row has not already been matched and saved previously

                        'LOOP THROUGH CURRENT TESTSTODELETE AND SEARCH FOR MATCH
                        If IsInTestsToDeleteAlready(CurrentTest) = True Then
                            'This row has already matched to another, continue loop search.

                        Else 'It is a match
                            'So to conclude this function, we return the current test
                            SeekEvilTwin = CurrentTest
                            Exit Function 'A chargeback can appear only once, search is over
                        End If

                    Else 'The date/time does not match, it must have been a simple credit for some other reason.
                        'Just because we found a same-named test and patient doesn't mean we can stop here.
                    End If 'End compare date/time

                Else 'The name & test did not match, do nothing and continue.
                End If 'End compare name and test.
            End With '(CurrentTest)

        Else 'The row contained a negative credit.
        End If 'End check charge amount.
    Next intY 'Next row

    'At the end of the loop all rows have been checked. We leave the default value of 0 to indicate no twin found anywhere.
    With SeekEvilTwin
        .dtDateTime = 0
        .intRow = 0
        .strPatientName = ""
        .strTestName = ""
    End With
End Function

Function IsInTestsToDeleteAlready(CurrentTest As DELETEDTESTS) As Boolean

    If UBound(TestsToDelete) <= 0 Then 'Just initialized and may be empty.
        If TestsToDelete(0).strPatientName = "" Then 'blank, empty
            IsInTestsToDeleteAlready = False
            Exit Function

        Else 'TestsToDelete has one item, continue
        End If 'end check blank TestsToDelete

    Else 'TestsToDelete is not empty
    End If 'End check TestsToDelete empty.

    Dim intX As Integer

    For intX = LBound(TestsToDelete) To UBound(TestsToDelete)
        With TestsToDelete(intX)
            If .dtDateTime = CurrentTest.dtDateTime And .intRow = CurrentTest.intRow And .strPatientName = CurrentTest.strPatientName And .strTestName = CurrentTest.strTestName Then
                IsInTestsToDeleteAlready = True
                Exit Function

            Else 'Not same, keep looking
            End If 'end compare if.
        End With

    Next intX

    IsInTestsToDeleteAlready = False 'If it got through the whole loop then there was no match.

End Function

Wow that’s a lot of code! Told you it would be complicated, but this is a great real-world example of the power of Excel vba.

Improvements are possible. For one thing, this macro makes rows of data disappear, it would be better to show the user what had been deleted. We could copy the deleted data to another worksheet or pop up a messagebox. Can you think of any other improvements?

In the final tutorial, I will show you how to make a custom drop-down menu to run the macros without having to pull up the macro dialog.

Next Tutorial: Adding custom Macro buttons to your Excel toolbar

Excel Macro Tutorial 1 – Open a text file

Excel Macro Tutorial 2 – Formatting the Columns and Column headers

Excel Macro Tutorial 3 – Remove header rows and delete junk loop

Excel Macro Tutorial 4 – Delete non-chargeable tests and sort

Excel Macro Tutorial 5 – Delete cancelled tests, flag credited tests

Excel Macro Tutorial 6 – Add macro buttons to your toolbar

Excel Macro Tutorial 4 – Delete non-chargeable tests and sort.

Author: ericains  |  Category: Computing

The billing report has a bunch of tests with at cpt code of ‘0’ or a blank.  These are non-chargeable tests.  We used to have to delete them manually.
bill report 0cpt
For this we can loop through the rows and delete non-chargeables just like we did with the junk removal.  For efficiency we could just add this code to the junk-removal macro, but I have kept them separate here for the sake of simplicity. I called the macro ‘DeleteZero’ and copied and modified from the last macro:


How to delete blank rows (and rows with 0 value) with an Excel macro:

Sub DeleteZero()
'Get FinalRow
'Loop through each row.
'Examine for 0 cpt
'Delete row if 0

Dim intX As Integer
Dim intFinalRow As Integer 'Final row
intFinalRow = Range("A65536").End(xlUp).Row 'From 'VBA and Macros for Microsoft Excel by Bill Jelen

intX = 2
Do While intX <= intFinalRow 'This for statement loops through each row on report one by one
    intFinalRow = Range("A65536").End(xlUp).Row 'From 'VBA and Macros for Microsoft Excel by Bill Jelen

    'We start at row 2, because 1st row had headers we want to keep
    'What is Cells?  This is just a different way of referring to excel cells.  Range("A1") is the same as Cells(1,1).
    'In the second part of this statement, we check for a blank cell by getting the value, convert it to a string, and trim it.
    If Cells(intX, 4).Value = 0 Or Trim(CStr(Cells(intX, 4).Value)) = "" Then 'Delete
        Rows(intX).Delete
        intX = intX - 1 'Since we deleted a row, we need to re-examine the row again, because excel moves the next row up a spot.
    End If

    'The loop will restart at the top until every row has been examined.
    intX = intX + 1 'At the end of the loop we are down with the current row, so we increment the counter by one.
Loop
End Sub

Now we’re supposed to sort by Patient name and Service Date.  Seems like it would be so easy.  I record my sort with the macro recorder:

 

Sub Sort()
'
' Sort Macro
'

'
    ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Clear
    ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add Key:=Range("A2:A140") _
        , SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
    ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add Key:=Range("H2:H140") _
        , SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
    With ActiveWorkbook.Worksheets("Sheet1").Sort
        .SetRange Range("A1:H140")
        .Header = xlYes
        .MatchCase = False
        .Orientation = xlTopToBottom
        .SortMethod = xlPinYin
        .Apply
    End With
End Sub

Uh-oh looks scary. Well there is it’s not too difficult to do this, but you probably would have had to study for awhile:

Sub Sort()
'
' Sort Macro
'

    'Lets walk through each line it recorded and make the changes.
    ActiveWorkbook.Worksheets(1).Range("A1").Select
    ActiveSheet.Sort.SortFields.Clear

    'See the problem here, it hard-coded in '140' as the last row.  Tomorrow the report may be '230' rows long.
    'Excel is smart enough to automatically detect the last row when you were doing the sort, why does it not record that? No Idea.
    intFinalRow = Range("A65536").End(xlUp).Row 'From 'VBA and Macros for Microsoft Excel by Bill Jelen

    'Going to use Cells(#,#) instead of ("A#:B#") again.
    'When you specify a range in A1 style it looks like: "Range("A2:A140")"
    'with cells it looks like this: "Range(Cells(2,1), Cells(140,1))"  - Note cells are separated by a comma and A1 style by a colon.
    'Dont get confused, with Cells the ROW comes first, then the COLUMN.  A1 notation is reversed.
    ActiveSheet.Sort.SortFields.Add Key:=Range(Cells(2, 1), Cells(intFinalRow, 1)) _
        , SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal

    ActiveSheet.Sort.SortFields.Add Key:=Range(Cells(2, 8), Cells(intFinalRow, 8)) _
        , SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal

    'We could use that FinalRow formula to get the last row, but there is an easier way.
    'Since the data is contiguous (no blank rows/columns between sections of the report) we can use CurrentRegion.
    With ActiveSheet.Sort
        .SetRange ActiveCell.CurrentRegion
        .Header = xlYes
        .MatchCase = False
        .Orientation = xlTopToBottom
        .SortMethod = xlPinYin
        .Apply
    End With
End Sub

In the next tutorial we will tackle the tricky stuff, finding cancelled tests and flagging chargebacks!

Excel Macro Tutorial 1 – Open a text file

Excel Macro Tutorial 2 – Formatting the Columns and Column headers

Excel Macro Tutorial 3 – Remove header rows and delete junk loop

Excel Macro Tutorial 4 – Delete non-chargeable tests and sort

Excel Macro Tutorial 5 – Delete cancelled tests, flag credited tests

Excel Macro Tutorial 6 – Add macro buttons to your toolbar

Excel Macro Tutorial 3 – Remove header rows and delete junk loop

Author: ericains  |  Category: Computing

Ok now we’re getting into a bit more advanced material.  We’re going to have the macro do some real grunt-work for us.  Here’s what we want it to do:
1. Find the last row of the report.
2. Go through the entire report, row by row, and delete anything that we don’t want.

The report has a bunch of junk we need to delete:
bill report junk

Simple enough, the only problem is you can’t just record yourself going through the report deleting stuff and then go back and change the code.  Reason being you’re using your brain and eyeballs to identify what is junk and what is not, and the macro recorder does not record brain and eyeball activity. 


How to delete junk data from an Excel spreadsheet with a macro:

This is where you would have to dig out your reference book, list what you are trying to do as I have above, and come up with the code.  This is what I came up with:

Sub JunkDelete()
'Get FinalRow
'Loop through each row.
'Examine for junk pattern
'Delete row if junk

Dim intX As Integer
Dim intFinalRow As Integer 'Final row
intFinalRow = Range("A65536").End(xlUp).Row 'From 'VBA and Macros for Microsoft Excel by Bill Jelen

intX = 2
Do While intX <= intFinalRow 'This for statement loops through each row on report one by one
    intFinalRow = Range("A65536").End(xlUp).Row 'From 'VBA and Macros for Microsoft Excel by Bill Jelen

    'We start at row 2, because 1st row had headers we want to keep
    Dim strCellText As String 'Variable holds text read from first cell
    Dim blnJunk As Boolean 'If the row is declared junk, it will be deleted.
    blnJunk = False 'Assume the row to be not junk to start.

    strCellText = CStr(Cells(intX, 1).Value) 'Get whatever is in column A of current row.
    Debug.Print "String read from cell " & intX & " was: " & strCellText 'While just starting to write the loop, you can use debug.print statments to check.

    'Now we do a series of comparisons to see if the row is junk.
    'Check for dashes.
    If InStr(strCellText, "---------------------") > 0 Then  'Dashes
        'InStr, short for "In String", looks to see if a certain string is found in another string.
        blnJunk = True
    End If

    'Check for a blank
    If Trim(strCellText) = "" Then 'Blank
        'Trim removes blank spaces from the front and end of a string, if the string is all blanks, you end up with nothing or ""
        blnJunk = True
    End If

    'Check for footer item "REPORT_ID:"
    If InStr(strCellText, "REPORT_ID") > 0 Then 'Found it
        blnJunk = True
    End If

    'Check for footer item "RETENTION:"
    If InStr(strCellText, "RETENTION") > 0 Then 'Found
        blnJunk = True
    End If

    'Check for header item "Patient Name"
    If InStr(strCellText, "Patient Name") > 0 Then 'found
        blnJunk = True
    End If

    'Check for footer item 'DATE:"
    If InStr(strCellText, "DATE:") > 0 Then  'found
        blnJunk = True
    End If

    'Testing is over, if row got flagged Junk, we need to delete the current row
    If blnJunk = True Then 'Delete
        Rows(intX).Delete
        intX = intX - 1 'Since we deleted a row, we need to re-examine the row again, because excel moves the next row up a spot.
    End If

    'The loop will restart at the top until every row has been examined.
    intX = intX + 1 'At the end of the loop we are down with the current row, so we increment the counter by one.
Loop

End Sub

Not too difficult after all.  I used a While loop instead of my favored For Next loop because of the ever-changing FinalRow and current row.  Also instead of a bunch of if statements I would have used a nested loop and an array, but there’s no need to complicate things here.

In the next tutorial we will handle sorting the list, looking for cancelled/charged-back tests and highlighting credited tests.

Excel Macro Tutorial 1 – Open a text file

Excel Macro Tutorial 2 – Formatting the Columns and Column headers

Excel Macro Tutorial 3 – Remove header rows and delete junk loop

Excel Macro Tutorial 4 – Delete non-chargeable tests and sort

Excel Macro Tutorial 5 – Delete cancelled tests, flag credited tests

Excel Macro Tutorial 6 – Add macro buttons to your toolbar

Excel Macro Tutorial 2 – Formatting the Columns and Column headers

Author: ericains  |  Category: Computing

We need to autosize the columns to fit the data and then change the background color of the column headers.

How to autosize columns with and Excel macro:

Autosizing the columns with a macro is very easy.  This is what the recorder recorded:

Sub ColumnsAutoSize()
  '

' ColumnsAutoSize Macro

'

    Columns("A:H").Select

    Selection.Columns.AutoFit

End Sub

Very simple, but we can still clean it up a bit. There is no reason to select anything in a macro usually. Anytime you see a ".Select" followed by a "Selection.", you can simply delete the selection stuff and combine it to one line:

Sub ColumnsAutoSize()
  '

' ColumnsAutoSize Macro

'

    Columns("A:H").Columns.AutoFit

End Sub

How to change background color of a cell in an Excel Macro:


That’s it for autosizing. Now adding a light gray background to the headers is a very simple matter:

Sub ColumnsAutoSize()
  '

' ColumnsAutoSize Macro

'

    Columns("A:H").Columns.AutoFit

    Range("A1:H1").Interior.ColorIndex = 15

End Sub

They also want us to format the E and G columns as currency. The recorder produces:

    Range("E:E,G:G").Select
    Selection.NumberFormat = "$#,##0.00"

We can simplify this and add it to the ColumnsAutoSize macro. Now that the macro does more than just autosizing, I will rename it too:

Sub ColumnsFormat()
  '

' ColumnsAutoSize Macro

'

    Columns("A:H").Columns.AutoFit

    Range("A1:H1").Interior.ColorIndex = 15

    Range("E:E,G:G").NumberFormat = "$#,##0.00"

End Sub

In the next tutorial I will show you how to remove junk headers and footers from the report

Excel Macro Tutorial 1 – Open a text file

Excel Macro Tutorial 2 – Formatting the Columns and Column headers

Excel Macro Tutorial 3 – Remove header rows and delete junk loop

Excel Macro Tutorial 4 – Delete non-chargeable tests and sort

Excel Macro Tutorial 5 – Delete cancelled tests, flag credited tests

Excel Macro Tutorial 6 – Add macro buttons to your toolbar

Excel Macro Tutorial 1 – Open a text file

Author: ericains  |  Category: Computing

In this 6-part series of tutorials, I show you how I was able to automate a process that took 5-10 minutes per report.  Now the process takes about 30 seconds.  The techniques and code examples from these tutorials can be adapted and used by anyone who has the misfortune of being delegated to do tedious gruntwork in Excel.  Many concepts like ‘how to record a macro in Excel’ are NOT covered in this tutorial.  There are plenty of tutorials on the web covering the basics of Excel macros.  Instead this tutorial fills in the gaps by explaining a real-world example from start to finish.


How to open a text file with an Excel Macro:

Often you have a text file report generated by the system that you have to import into Excel.  After importing you manipulate, sort, and format the data.  This process is repetitive and can be automated using an Excel macro.

For this tutorial I will show you how I made a macro to automate a daily billing report generated by the lab system.
bill report head

The text file is always in the same format, so we can automate this part of the process.   The lab system lets us save this report as a text file. 
Even seasoned macro writers will record their actions in excel first and then modify the recorded code.
So I click the record macro button in Excel and record the steps I take to open the file.
In excel I open the text file and use the import data wizard that pops up:
bill report import

Instead of recording ALL the stuff I do with the report I prefer to take it step by step.  This makes it easier to understand and easier to troubleshoot or modify later on.  I recorded the opening of the text file and here is the resulting code:

.

Sub OpenBillingTextFile()
'
' OpenBillingTextFile Macro
' Macro recorded 11/15/2009 by wlbueaa
'

'
    Workbooks.OpenText Filename:= _
        "K:\HL2GEN05\Eric\Billing 11152009.txt", Origin:= _
        437, StartRow:=9, DataType:=xlFixedWidth, FieldInfo:=Array(Array(0, 1), _
        Array(25, 1), Array(35, 1), Array(74, 1), Array(82, 1), Array(93, 1), Array(100, 1), Array( _
        110, 1)), TrailingMinusNumbers:=True
End Sub

Be sure to give your macro a descriptive name instead of ‘Macro1’ or something.

Now we can modify this recorded code to make it possible to open subsequent files in the same fashion.

Clearly we can’t have the macro opening the same file each time.  So I’ll use the code the macro recorded and add a file open dialog so the user can select the file to open:

Sub OpenBillingTextFile()
'
' OpenBillingTextFile Macro
' Macro recorded 11/15/2009 by wlbueaa
'

'
Dim FileName As String
FileName = Application.GetOpenFilename(FileFilter:="Text Files (*.txt), *.txt,dat (*.dat), *.dat", Title:="Please select a file")

If CStr(FileName) <> "False"
    Workbooks.OpenText FileName:= _
        FileName, Origin:= _
        437, StartRow:=9, DataType:=xlFixedWidth, FieldInfo:=Array(Array(0, 1), _
        Array(25, 1), Array(35, 1), Array(74, 1), Array(82, 1), Array(93, 1), Array(100, 1), Array( _
        110, 1)), TrailingMinusNumbers:=True

Else 'user pressed cancel
End If
End Sub

So we’ve saved several steps here.  Now instead of clicking File-Open and going through the text file import wizard we just run the macro and select the file!

Look at the difference between the recorded code and the modified code. With the new macro the user will get an open file dialog box that lets them browse for text files to open.

If you are asking "Where did you get this command ‘Application.GetOpenFileName’?", I will answer your question with another question: "Where do you go to get any commands and code for Excel Macros?". 3 places: Google, Amazon books, and forums/blogs. Reference books on excel vba are great to have handy for looking up how to do something. As for Google, you search for "vba code to open a file" and see where it takes you. Finally after Googling for awhile you will usually find a forum or blog dedicated to excel vba where you can get all kinds of free advice. I will gather up my favorite books and forums and list them at the end of this series.

Back to the macro:

Just getting to the macro player window is a bit of a chore, so in the last part of this tutorial I will show you how to add a custom menu directly into your copy of Excel!

In the next tutorials I will go through how to create macros to format the columns, remove junk headers and footers, check for duplicate tests, delete non-chargeable tests, and flag credited tests!

Next: Formatting the columns and column headers.

Excel Macro Tutorial 1 – Open a text file

Excel Macro Tutorial 2 – Formatting the Columns and Column headers

Excel Macro Tutorial 3 – Remove header rows and delete junk loop

Excel Macro Tutorial 4 – Delete non-chargeable tests and sort

Excel Macro Tutorial 5 – Delete cancelled tests, flag credited tests

Excel Macro Tutorial 6 – Add macro buttons to your toolbar

Lab Jokes – You know your instrument is a piece of junk when…

Author: ericains  |  Category: Jokes

You Know your instrument is a piece of junk when…

1. You know the service guy on a first-name basis and have even considered inviting him over for beers sometime.

2. You know the serial number of your instrument by heart from reciting it to tech support so many times.

3. You have actually physically assaulted the instrument while no one was looking.

4. Everyone knows you physically assault the instrument but they never tell anyone about it.

5. You’ve been in your supervisors office more than once threatening to quit – (“It’s either Me or that piece of S#@T!!!”)

6. Other lab techs gather and egg you on, as you physically assault the helpless instrument.

7. After troubleshooting the instrument for hours, you’ve had to go to a storeroom or office and close the door to calm down for awhile.

8. It becomes routine for you to spend the first thirty minutes of the next shifts time explaining and apologizing for unresolved problems with the instrument.

9. You’ve come close to tears when explaining the instruments quirks to new employees or students.

10. While training new employees their eyes glaze over as you try to make impossibly complex troubleshooting techniques as straightforward as possible.

11. Your supervisor will not let you take vacation until you’ve trained a new hire enough that they feel ‘comfortable with it’.

12. The more the new hire learns about the instrument the quieter and more distant he/she gets.

13. You frequently notice the new hire browsing online job sites and working on his/her resume’.

14. You go to a training event for the instrument and the question-answer session at the end of class ends up being more like a town-hall meeting.

15. You inexplicably lash out at a friend from another lab when they mention that their instrument is ‘pretty easy to maintain.’

16. You’ve had a nightmare where the instrument gave you an error code you’ve never seen before.
Unknown Error

17. Overhearing the name of the instrument triggers a facial tic.

See the comments below for more!

 

SynapSonic Software

Author: ericains  |  Category: Info
SynapSonic Software produces software for medical laboratory and general use:

Along with commercial software I have also written a few other programs.

Download these Free, useful SynapSonic utilities here! database_down


Ol Monitor Ol Monitor is a turn-around-time management and acceleration tool for labs using the Misys lab information system.  OL_Monitor is a program that interacts with the Misys™ (Formerly Sunquest™) Laboratory information system. OL_Monitor integrates seamlessly with Esker™ Smarterm, the client of choice for most laboratories. Like a tireless unblinking eye, it keeps up with the Outstanding log. In addition it adds critical information the Outstanding log lacks, how long tests have been outstanding. This is just the beginning, read on to find out.

Share your Lab Jokes

Author: ericains  |  Category: Jokes

Feel free to post any jokes you heard lately.  Or if you’ve found one on the web somewhere add a link!

Lab Jokes – Q&A

Author: ericains  |  Category: Jokes

Medical Lab Jokes – Q&A

Q: What type of red cell will be observed on the peripheral smear if blood was refrigerated prior to making the smear?
A: A brrrr cell.  -Credit: (I’ve known this one so long I may have made it up myself.)