VBA Code


Shading Cells

The best way to shade cells is to define the ColorIndex property and assign it to the corresponding colour palette number.

Range("A1:B10").Interior.ColorIndex = 17 

Range("A1:B10").Interior.ColorIndex = xlColorIndex.xlColorIndexAutomatic 
Range("A1:B10").Interior.ColorIndex = Excel.xlAutomatic

The second line is only made available for backwards compatibility.


objRange.ClearContents  'values and formulas  
objRange.Clear 'values, formulas and formatting
objRange.ClearFormats 'clears just formatting (inc conditional formatting)
objRange.ClearNotes
objRange.ClearComments
objRange.ClearOutline

Using Colours

Range("A1:B10").Interior.Color = RGB(153,51,102) 

Checking for any shading

If (ActiveCell.Interior.ColorIndex <> xlNone) Then 

Removing Shading

Range("A1:B10").Interior.ColorIndex = xlColorIndex.xlColorIndexNone 
Range("A1:B10").Interior.ColorIndex = Excel.xlNone

The second line is only made available for backwards compatibility.


Adding Patterns

The default Pattern is solid.

Range("A1:B10").Interior.Pattern = xlPattern.xlSolid 

Merging Cells

Range("A1:B1").Merge 
Range("A1:B1").MergeCells = True

Also see the Format Dialog Box page


MergeArea Property

Returns a Range object that represents the merged range containing the specified cell
If the specified cell isn't in a merged range, this property returns the specified cell
This property only works on a single cell range

Dim objMergeArea As Range 
Set objMergeArea = Range("A3").MergeArea
If objMergeArea.Address = "$A$3" Then
   Call MsgBox (not merged")
Else
   objMergeArea.Cells(1,1).Value = "hello"
End If

Wrapping Text

Range("A1").WrapText = True 

??

Range("A2").Font.Italic = False 
Range("D10").Font.Bold = True
Rows(3).Font.Bold = True
Cells(2,4).BorderAround Weight:=xlMedium
ActiveSheet.Rows(5).Font.Size = 10
ActiveSheet.Rows(2:10).Font.Name = "Arial"

The available font size using VBA is 1 to 127 although the formatting toolbar only lists 8 to 72. If you do not have the chosen font installed then Excel will substitute the closest match.
When formatting text, there is a font.fontstyle property but I would not suggest using this. It is better to explicitly specify whether bold, italics etc.


When you change the background or font colour of a cell, Excel does not consider this to be changing the value of the cell and will not generate a Worksheet_Change() event.


Clears the formulas and formatting

objRange.Clear 


Application.FindFormat 
Application.ReplaceFormat


The Colors property returns or sets the colours defined in the colour palette.
The colour palette has 56 colours.


ActiveWorkbook.Colors(1) = RGB(50, 100, 150) 

If the Index property is not specified then the Colors property will return an array containing all 56 colours.

Dim avArray As Variant 
   avArray = ActiveWorkbook.Colors()

You can quickly reset all the colours in a workbook.

ActiveWorkbook.ResetColors 

Format Cells Dialog Box


Number tab

Range.NumberFormat = "@"          'text  
Range.NumberFormat = "0" 'no decimal places
Range.NumberFormat = "0.00" 'two decimal places
Range.NumberFormat = "General" 'general
Range.NumberFormat = "0.00%" 'percentage

Application.DecimalSeparator 
UseSystemSeparators

Alignment tab

With Selection 
    .HorizontalAlignment = xlHAlign.xlHAlignGeneral
    .VerticalAlignment = xlVAlign.xlVAlignBottom
    .AddIndent = False
    .IndentLevel = 0 - 15

    .WrapText = False
    .ShrinkToFit = False
    .MergeCells = False

    .Orientation = 40

'for some reason this is not an enumeration ?
    .ReadingOrder = Excel.Constants.xlRTL
    .ReadingOrder = Excel.Constants.xlLTR
    .ReadingOrder = Excel.Constants.xlContext
End With

Font tab

The Normal font checkbox just returns all the properties back to the default values.
Some of these properties can also return Nothing (and not just True or False). It is safer to use variant variables when analysing and changing the properties.

With Selection.Font 
    .Name = "Arial"
    .FontStyle = "Regular" '(in C# this does not exist as there are specific properties for Bold and Italic
    .Size = 10
    .Bold = False
    .Underline = xlUnderlineStyle.xlUnderlineStyleNone

    .Color = RGB(30,30,30)
'when you select Automatic the color index used is 0
    .ColorIndex = xlColorIndex.xlColorIndexAutomatic | 0 | 53

    .Strikethrough = False
    .Superscript = False
    .Subscript = False

'This is true if the font selected in an outline font - This has no effect in Windows
    .OutlineFont = False

'This is true if the font selected in an outline font - This has no effect in Windows
    .Shadow = False
End With

Border tab

You can use either ColorIndex or Color, but not both.
You can specify both the LineStyle and the Weight. If you do not specify them then the default will be used.


linestyle=xlNonelinestyle=xlDashDotDot; weight=xlMedium
linestyle=xlContinuous; weight=xlHairlinelinestyle=xlSlantDashDot; weight=xlMedium
linestyle=xlDot; weight=xlThinlinestyle=xlDashDot; weight=xlMedium
linestyle=xlDashDotDot; weight=xlThinlinestyle=xlDash; weight=xlMedium
linestyle=xlDashDot; weight=xlThinlinestyle=xlContinuous; weight=xlMedium
linestyle=xlDash; weight=xlThinlinestyle=xlContinuous; weight=xlThick
linestyle=xlContinuous; weight=xlThinlinestyle=xlDouble; weight=xlThick

Selection.Borders(xlBordersIndex.xlEdgeLeft).LineStyle = xlLineStyle.xlContinuous 
Selection.Borders(xlBordersIndex.xlEdgeLeft).Weight = xlBorderWeight.xlThin
Selection.Borders(xlBordersIndex.xlEdgeLeft).ColorIndex = xlColorIndex.xlColorIndexAutomatic | 53
Selection.Borders(xlBordersIndex.xlEdgeLeft).Color = RGB(10,10,10)

Selection.Borders(xlBordersIndex.xlEdgeTop).LineStyle = xlLineStyle.xlContinuous
Selection.Borders(xlBordersIndex.xlEdgeTop).Weight = xlBorderWeight.xlThin
Selection.Borders(xlBordersIndex.xlEdgeTop).ColorIndex = xlColorIndex.xlColorIndexAutomatic | 53

Selection.Borders(xlBordersIndex.xlEdgeBottom).LineStyle = xlLineStyle.xlContinuous
Selection.Borders(xlBordersIndex.xlEdgeBottom).Weight = xlBorderWeight.xlThin
Selection.Borders(xlBordersIndex.xlEdgeBottom).ColorIndex = xlColorIndex.xlColorIndexAutomatic | 53

Selection.Borders(xlBordersIndex.xlEdgeRight).LineStyle = xlLineStyle.xlContinuous
Selection.Borders(xlBordersIndex.xlEdgeRight).Weight = xlBorderWeight.xlThin
Selection.Borders(xlBordersIndex.xlEdgeRight).ColorIndex = xlColorIndex.xlColorIndexAutomatic | 53

You cannot define an InsideVertical border if the Range has no inside vertical borders (i.e. only 1 cell).
Assigning an InsideVertical on a single cell will generate an error.

Selection.Borders(xlBordersIndex.xlInsideVertical).LineStyle = xlLineStyle.xlContinuous 
Selection.Borders(xlBordersIndex.xlInsideVertical).Weight = xlBorderWeight.xlThin
Selection.Borders(xlBordersIndex.xlInsideVertical).ColorIndex = xlColorIndex.xlColorIndexAutomatic | 53

You cannot define an InsideHorizontal border if the Range has no inside vertical borders (i.e. only 1 cell).
Assigning an InsideHorizontal on a single cell will generate an error.

Selection.Borders(xlBordersIndex.xlInsideHorizontal).LineStyle = xlLineStyle.xlContinuous 
Selection.Borders(xlBordersIndex.xlInsideHorizontal).Weight = xlBorderWeight.xlThin
Selection.Borders(xlBordersIndex.xlInsideHorizontal).ColorIndex = xlColorIndex.xlColorIndexAutomatic | 53

Selection.Borders(xlBordersIndex.xlDiagonalDown).LineStyle = Excel.xlNone
Selection.Borders(xlBordersIndex.xlDiagonalUp).LineStyle = Excel.xlNone

You can also remove all the borders using this single line

Selection.Borders.LineStyle = xlLineStyle.xlLineStyleNone 

Fill tab

This was called the Patterns tab in 2003.

Selection.Interior.Color = RGB(120,120,120) 
Selection.Interior.ColorIndex = (old 2003)

There is a Patterns property that corresponds to the Patterns tab on this dialog box.

Selection.Interior.Pattern = xlPattern.xlPatternNone 
Selection.Interior.Pattern = xlPattern.xlLightDown

The other properties are only relevant when the Interior.Pattern property is not xlPatternNone.


The PatternColorIndex property can be either an index into the current colour palette, or as one of the following xlColorIndex constants

Selection.Interior.PatternColorIndex = 42 

This can be used when you don't want a pattern. This is the same as setting the Interior.Pattern property to xlPatternNone

Selection.Interior.PatternColorIndex = xlColorIndex.xlColorIndexNone 

This can be used to select the automatic pattern.

Selection.Interior.PatternColorIndex = xlColorIndex.xlColorIndexAutomatic 

Selection.Interior.ThemeColor = xlThemeColor.xlThemeColorAccent1 
Selection.Interior.TintAndShade = -0.24994659

Selection.Interior.PatternThemeColor = xlThemeColor.xlThemeColorAccent2 
Selection.Interior.PatternTintAndShade =
Selection.Interior.Gradient.Degree = 90
Selection.Interior.Gradient.ColorStops.Clear
Selection.Interior.Gradient.ColorStops.Add(0).ThemeColor =
Selection.Interior.Gradient.ColorStops.Add(0).TintAndShade =

Protection tab

Selection.Locked = False 
Selection.FormulaHidden = True

Please refer to the Protection section for more details.


Formatting Characters

It is possible to format different parts of a text string with the help of some VBA code.
Lets suppose we want to change the formatting of the following text so the different components are displayed in different colours and formatted differently.
Please note that this method cannot be used to format dates, only text entries.

The following lines of code loop through all the cells and manually change the formatting of each cell.

Range("B2").Select 
Do While Len(ActiveCell.Value) > 0
   ActiveCell.Characters(Start:=1, Length:=2).Font.ColorIndex = 9
   ActiveCell.Characters(Start:=1, Length:=2).Font.Bold = True
   ActiveCell.Characters(Start:=4, Length:=2).Font.ColorIndex = 22
   ActiveCell.Characters(Start:=4, Length:=2).Font.Italic = True
   ActiveCell.Characters(Start:=7, Length:=4).Font.ColorIndex = 49
   ActiveCell.Characters(Start:=7, Length:=4).Font.Underline = True
   ActiveCell.Offset(1,0).Select
Loop

Delete Unused Custom Formats

This procedure provides a workaround for the glaring lack of accessibility in VBA for manipulating custom number formats.
To do this, it hacks into the Number Format dialog box with SendKeys.
It loops through each item, including those custom number formats that have been orphaned from the worksheet.
The dialog box flickers upon each opening, but it works! If anyone comes up with a way to eliminate the flicker, let me know.


Sub DeleteUnusedCustomNumberFormats() 
    Dim Buffer As Object
    Dim Sh As Object
    Dim SaveFormat As Variant
    Dim fFormat As Variant
    Dim nFormat() As Variant
    Dim xFormat As Long
    Dim Counter As Long
    Dim Counter1 As Long
    Dim Counter2 As Long
    Dim StartRow As Long
    Dim EndRow As Long
    Dim Dummy As Variant
    Dim pPresent As Boolean
    Dim NumberOfFormats As Long
    Dim Answer
    Dim c As Object
    Dim DataStart As Long
    Dim DataEnd As Long
    Dim AnswerText As String

    NumberOfFormats = 1000
    ReDim nFormat(0 To NumberOfFormats)
    AnswerText = "Do you want to delete unused custom formats from the workbook?"
    AnswerText = AnswerText & Chr(10) & "To get a list of used and unused formats only, choose No."
    Answer = MsgBox(AnswerText, 259)
    If Answer = vbCancel Then GoTo Finito

    On Error GoTo ErrorHandler
    Worksheets.Add.Move after:=Worksheets(Worksheets.Count)
    Worksheets(Worksheets.Count).Name = "CustomFormats"
    Worksheets("CustomFormats").Activate
    Set Buffer = Range("A2")
    Buffer.Select
    nFormat(0) = Buffer.NumberFormatLocal
    Counter = 1
    Do
        SaveFormat = Buffer.NumberFormatLocal
        Dummy = Buffer.NumberFormatLocal
        DoEvents
        SendKeys "{tab 3}{down}{enter}"
        Application.Dialogs(xlDialogFormatNumber).Show Dummy
        nFormat(Counter) = Buffer.NumberFormatLocal
        Counter = Counter + 1
    Loop Until nFormat(Counter - 1) = SaveFormat

    ReDim Preserve nFormat(0 To Counter - 2)

    Range("A1").Value = "Custom formats"
    Range("B1").Value = "Formats used in workbook"
    Range("C1").Value = "Formats not used"
    Range("A1:C1").Font.Bold = True

    StartRow = 3
    EndRow = 16384

    For Counter = 0 To UBound(nFormat)
        Cells(StartRow, 1).Offset(Counter, 0).NumberFormatLocal = nFormat(Counter)
        Cells(StartRow, 1).Offset(Counter, 0).Value = nFormat(Counter)
    Next Counter

    Counter = 0
    For Each Sh In ActiveWorkbook.Worksheets
        If Sh.Name = "CustomFormats" Then Exit For
        For Each c In Sh.UsedRange.Cells
            fFormat = c.NumberFormatLocal
            If Application.WorksheetFunction.CountIf(Range(Cells(StartRow, 2), Cells(EndRow, 2)), fFormat) = 0 Then
                Cells(StartRow, 2).Offset(Counter, 0).NumberFormatLocal = fFormat
                Cells(StartRow, 2).Offset(Counter, 0).Value = fFormat
                Counter = Counter + 1
            End If
        Next c
    Next Sh

    xFormat = Range(Cells(StartRow, 2), Cells(EndRow, 2)).Find("").Row - 2
    Counter2 = 0
    For Counter = 0 To UBound(nFormat)
        pPresent = False
        For Counter1 = 1 To xFormat
            If nFormat(Counter) = Cells(StartRow, 2).Offset(Counter1, 0).NumberFormatLocal Then
                pPresent = True
            End If
        Next Counter1
        If pPresent = False Then
            Cells(StartRow, 3).Offset(Counter2, 0).NumberFormatLocal = nFormat(Counter)
            Cells(StartRow, 3).Offset(Counter2, 0).Value = nFormat(Counter)
            Counter2 = Counter2 + 1
        End If
    Next Counter
    With ActiveSheet.Columns("A:C")
        .AutoFit
        .HorizontalAlignment = xlLeft
    End With
    If Answer = vbYes Then
        DataStart = Range(Cells(1, 3), Cells(EndRow, 3)).Find("").Row + 1
        DataEnd = Cells(DataStart, 3).Resize(EndRow, 1).Find("").Row - 1
        On Error Resume Next
        For Each c In Range(Cells(DataStart, 3), Cells(DataEnd, 3)).Cells
            ActiveWorkbook.DeleteNumberFormat (c.NumberFormat)
        Next c
    End If

ErrorHandler:
    Set c = Nothing
    Set Sh = Nothing
    Set Buffer = Nothing
End Sub


Public Sub ListAllFormats() 

Dim iwshcount As Integer
Dim objWorksheet As Worksheet
Dim llastrow As Long
Dim ilastcolumn As Integer
Dim lRowNo As Long
Dim icolno As Integer
Dim arUniqueFormats2() As String
Dim objFSODictionary As Scripting.Dictionary
Dim objFSOUniqueTotals As Scripting.Dictionary
Dim objFSOWorksheetNames_Column As Scripting.Dictionary
Dim arUniqueWorksheetKeys As Variant
Dim snumberformat As String
Dim isheetandformatcount As Integer
Dim lcurrentrow As Long
Dim scellpattern As String
Dim scellstyle As String
Dim slastcolchar As String

   On Error GoTo AnError
   ReDim arUniqueFormats2(4, (3000 * ActiveWorkbook.Worksheets.Count)) As String
   Set objFSODictionary = New Scripting.Dictionary
   Set objFSOUniqueTotals = New Scripting.Dictionary
   Set objFSOWorksheetNames_Column = New Scripting.Dictionary

   For iwshcount = 1 To ActiveWorkbook.Worksheets.Count
      Set objWorksheet = ActiveWorkbook.Worksheets(iwshcount)
      If (objWorksheet.Name <> "Sheet1") Then
      
         If (objWorksheet.Visible <> xlSheetVisible) Then
            objWorksheet.Visible = xlSheetVisible
         End If
         If (objFSOWorksheetNames_Column.Exists(objWorksheet.Name) = False) Then
            objFSOWorksheetNames_Column.Add objWorksheet.Name, iwshcount - 1
         End If
      
         objWorksheet.Select
         llastrow = Range("A1").SpecialCells(XlCellType.xlCellTypeLastCell).Row
         ilastcolumn = Range("A1").SpecialCells(XlCellType.xlCellTypeLastCell).Column
              
         For lRowNo = 1 To llastrow
            For icolno = 1 To ilastcolumn
               snumberformat = Cells(lRowNo, icolno).NumberFormatLocal
               Call UniqueFormatsPopulate("Number Format", snumberformat, lRowNo, icolno, objWorksheet.Name, _
                                          objFSODictionary, objFSOUniqueTotals, arUniqueFormats2)
               
               scellpattern = Cells(lRowNo, icolno).Interior.ColorIndex
               Call UniqueFormatsPopulate("Shading Pattern", scellpattern, lRowNo, icolno, objWorksheet.Name, _
                                          objFSODictionary, objFSOUniqueTotals, arUniqueFormats2)
                                          
               scellstyle = Cells(lRowNo, icolno).Style
               Call UniqueFormatsPopulate("Style", scellstyle, lRowNo, icolno, objWorksheet.Name, _
                                          objFSODictionary, objFSOUniqueTotals, arUniqueFormats2)
                          
            Next icolno
         Next lRowNo
      End If
   Next iwshcount
     
   ReDim Preserve arUniqueFormats2(4, objFSOUniqueTotals.Count - 1)
   arUniqueFormats2 = SortArray(arUniqueFormats2)
   Worksheets("Sheet1").Select
   Cells.Clear
   Cells.ClearFormats
        
'display worksheets across the top
   Range("C2").Value = "TOTAL"
   arUniqueWorksheetKeys = objFSOWorksheetNames_Column.Keys()
   For iwshcount = 0 To UBound(arUniqueWorksheetKeys, 1)
      Cells(2, 4 + iwshcount).Value = arUniqueWorksheetKeys(iwshcount)
   Next iwshcount
           
   slastcolchar = Col_Letter(UBound(arUniqueWorksheetKeys, 1) + 4)
           
'display unique formats down left hand side - start by creating a list of unique formats
   llastrow = 3
   llastrow = PopulateTableWithCategory(slastcolchar, objFSODictionary, objFSOWorksheetNames_Column, arUniqueFormats2, "Number Format", llastrow)
   llastrow = llastrow + 2
   llastrow = PopulateTableWithCategory(slastcolchar, objFSODictionary, objFSOWorksheetNames_Column, arUniqueFormats2, "Shading Pattern", llastrow)
   llastrow = llastrow + 2
   llastrow = PopulateTableWithCategory(slastcolchar, objFSODictionary, objFSOWorksheetNames_Column, arUniqueFormats2, "Style", llastrow)
        
    
   Exit Sub
AnError:
   MsgBox (Err.Number & " - " & Err.Description)
End Sub
'**************************************************************************************
Public Sub UniqueFormatsPopulate(ByVal sCategoryName As String, _
                                 ByVal sFormat As String, _
                                 ByVal lRowNo As Long, _
                                 ByVal icolno As Integer, _
                                 ByVal sWshName As String, _
                                 ByRef objFSODictionary As Scripting.Dictionary, _
                                 ByRef objFSOUniqueTotals As Scripting.Dictionary, _
                                 ByRef arUniqueFormats As Variant)

   On Error GoTo AnError

   If (objFSODictionary.Exists(sCategoryName & sWshName & "!!" & sFormat) = True) Then
      objFSODictionary(sCategoryName & sWshName & "!!" & sFormat) = _
         objFSODictionary(sCategoryName & sWshName & "!!" & sFormat) + 1
   
      arUniqueFormats(3, objFSOUniqueTotals(sCategoryName & sWshName & "!!" & sFormat)) = _
         arUniqueFormats(3, objFSOUniqueTotals(sCategoryName & sWshName & "!!" & sFormat)) & "-" & Cells(lRowNo, icolno).Address
   
   Else
      objFSODictionary.Add sCategoryName & sWshName & "!!" & sFormat, 1
      objFSOUniqueTotals.Add sCategoryName & sWshName & "!!" & sFormat, (objFSOUniqueTotals.Count)
   
      arUniqueFormats(0, objFSOUniqueTotals.Count - 1) = sCategoryName
     arUniqueFormats(1, objFSOUniqueTotals.Count - 1) = sWshName
      arUniqueFormats(2, objFSOUniqueTotals.Count - 1) = sFormat
      arUniqueFormats(3, objFSOUniqueTotals.Count - 1) = Cells(lRowNo, icolno).Address
      arUniqueFormats(4, objFSOUniqueTotals.Count - 1) = sCategoryName & sWshName & sFormat
   End If

   Exit Sub
AnError:
   MsgBox (Err.Number & " - " & Err.Description)
End Sub
'**************************************************************************************
Public Function PopulateTableWithCategory(ByVal slastcolchar As String, _
                                          ByVal objFSODictionary As Scripting.Dictionary, _
                                          ByVal objFSOWorksheetNames_Column As Scripting.Dictionary, _
                                          ByVal arUniqueFormats As Variant, _
                                          ByVal sCategory As String, _
                                          ByVal llastrow As Long) As Long
                                          
Dim objFSOUniqueFormats_Rows As Scripting.Dictionary
Dim arUniqueFormatKeys As Variant
Dim lRowNo As Long

   On Error GoTo AnError

   Set objFSOUniqueFormats_Rows = New Scripting.Dictionary
   Set objFSOUniqueFormats_Rows = ReturnUniqueFormatsForACategory(arUniqueFormats, sCategory)
   
   arUniqueFormatKeys = objFSOUniqueFormats_Rows.Keys
   For lRowNo = 0 To UBound(arUniqueFormatKeys, 1)
      Range("A" & lRowNo + llastrow).Value = sCategory
      Range("B" & lRowNo + llastrow).Value = "''" & arUniqueFormatKeys(lRowNo)
      Range("C" & lRowNo + llastrow).Value = "=SUM(D" & lRowNo + llastrow & ":" & _
                                                   slastcolchar & lRowNo + llastrow & ")"
      
      If (sCategory = "Shading Pattern") Then
         If (arUniqueFormatKeys(lRowNo) <> "-4142") Then
            Range("B" & lRowNo + llastrow).Interior.ColorIndex = arUniqueFormatKeys(lRowNo)
         End If
      End If
      
   Next lRowNo
   
   Rows("2:2").Font.Bold = True
   Columns("B:C").Font.Bold = True
'Columns("A").ColumnWidth = 3
   Columns("A:B").EntireColumn.AutoFit
       
   For lRowNo = 0 To UBound(arUniqueFormats, 2)
      If (arUniqueFormats(0, lRowNo) = sCategory) Then
         Cells((llastrow - 1) + objFSOUniqueFormats_Rows.Item(arUniqueFormats(2, lRowNo)), _
               3 + objFSOWorksheetNames_Column.Item(arUniqueFormats(1, lRowNo))).Value = _
            objFSODictionary(sCategory & arUniqueFormats(1, lRowNo) & "!!" & arUniqueFormats(2, lRowNo))
      End If
   Next lRowNo
        
   PopulateTableWithCategory = llastrow + UBound(arUniqueFormatKeys, 1)
        
   Exit Function
AnError:
   MsgBox (Err.Number & " - " & Err.Description)
End Function
'**************************************************************************************
Public Function ReturnUniqueFormatsForACategory(ByVal arUniqueFormats As Variant, _
                                                ByVal sCategory As String) As Scripting.Dictionary
Dim lRowNo As Long
Dim icolno As Integer
Dim objFSOUniqueFormats As Scripting.Dictionary

   On Error GoTo AnError
   Set objFSOUniqueFormats = New Scripting.Dictionary
   
   icolno = 1
   For lRowNo = 0 To UBound(arUniqueFormats, 2)
      If (arUniqueFormats(0, lRowNo) = sCategory) Then
         If (objFSOUniqueFormats.Exists(arUniqueFormats(2, lRowNo)) = False) Then
            objFSOUniqueFormats.Add arUniqueFormats(2, lRowNo), icolno
            icolno = icolno + 1
         End If
      End If
   Next lRowNo
   
   Set ReturnUniqueFormatsForACategory = objFSOUniqueFormats
   Exit Function
AnError:
   MsgBox (Err.Number & " - " & Err.Description)
End Function
'**************************************************************************************
Public Function SortArray(ByVal arArray As Variant) As Variant

Dim Temp As Variant
Dim i As Long
Dim j As Long

ReDim Temp(4) As String

   On Error GoTo AnError
   
    For i = LBound(arArray, 2) To (UBound(arArray, 2) - 1)
        For j = (i + 1) To (UBound(arArray, 2))
        
            If arArray(4, i) > arArray(4, j) Then
            
                Temp(0) = arArray(0, j)
                Temp(1) = arArray(1, j)
                Temp(2) = arArray(2, j)
                Temp(3) = arArray(3, j)
                Temp(4) = arArray(4, j)
                
                arArray(0, j) = arArray(0, i)
                arArray(1, j) = arArray(1, i)
                arArray(2, j) = arArray(2, i)
                arArray(3, j) = arArray(3, i)
                arArray(4, j) = arArray(4, i)
                
                arArray(0, i) = Temp(0)
                arArray(1, i) = Temp(1)
                arArray(2, i) = Temp(2)
                arArray(3, i) = Temp(3)
                arArray(4, i) = Temp(4)
            End If
        Next j
    Next i
   SortArray = arArray
   
   Exit Function
AnError:
   MsgBox (Err.Number & " - " & Err.Description)
End Function
'**************************************************************************************
Public Function Col_Letter(ByVal icolno As Integer) As String
Dim inumber1 As Integer
On Error GoTo AnError
    Select Case icolno
       Case 0: Col_Letter = Chr(90)
      Case Is <= 26: Col_Letter = Chr(icolno + 64)
       Case Else
          inumber1 = Int((64 + ((icolno - 1) / 26)))
          Col_Letter = Chr(inumber1) & Chr(((icolno - 1) Mod 26) + 65)
    End Select
   Exit Function
AnError:
  Call MsgBox("Unable to return the corresponding letter for the column number " & _
              "'" & icolno & "'.")
End Function

Public Sub DeleteUnusedCustomNumberFormats() Dim aFormatsArray() As Variant Dim lRowLast_A As Long, lRowLast_B As Long, lRowLast_C As Long, lRowLast_D As Long Dim larraycount As Long, lCounter As Long, linside As Long, lrowno As Long, lTotalRemoved As Long Dim wsh As Excel.Worksheet Dim sFormat As String Dim cell As Excel.Range Dim bExists As Boolean 

    On Error GoTo ErrorHandler
    If (AskForConfirmation = False) Then Exit Sub
    Worksheets.Add.Move after:=Worksheets(Worksheets.Count)
    Worksheets(Worksheets.Count).Name = "CustomFormats"
    Worksheets("CustomFormats").Activate

'------------------ formats available
    aFormatsArray = GetListOfNumberFormats(Range("A2"), False)
    For larraycount = 0 To UBound(aFormatsArray)
        Worksheets("CustomFormats").Range("A" & larraycount + 2).Value = aFormatsArray(larraycount)
    Next larraycount
    lRowLast_A = Worksheets("CustomFormats").Range( _
               Worksheets("CustomFormats").Range("A5000").End(XlDirection.xlUp).Address).Row
    Worksheets("CustomFormats").Range("A2:A" & lRowLast_A).Sort _
       Key1:=Worksheets("CustomFormats").Range("A2"), Order1:=xlAscending
       
'------------------ formats used
    lCounter = 0
    For Each wsh In ActiveWorkbook.Worksheets
        If wsh.Name = "CustomFormats" Then Exit For
        For Each cell In wsh.UsedRange.Cells
            sFormat = cell.NumberFormatLocal
            If Application.WorksheetFunction.CountIf(Worksheets("CustomFormats").Range("B:B"), sFormat) = 0 Then
                Worksheets("CustomFormats").Range("B" & lCounter + 2).NumberFormatLocal = sFormat
                Worksheets("CustomFormats").Range("B" & lCounter + 2).Value = sFormat
                lCounter = lCounter + 1
            End If
        Next cell
    Next wsh
    lRowLast_B = Worksheets("CustomFormats").Range( _
               Worksheets("CustomFormats").Range("B5000").End(XlDirection.xlUp).Address).Row
    Worksheets("CustomFormats").Range("B2:B" & lRowLast_B).Sort _
       Key1:=Worksheets("CustomFormats").Range("B2"), Order1:=xlAscending
               
               
'------------------ formats not used - those in red are not even valid formats
    lRowLast_A = Worksheets("CustomFormats").Range( _
               Worksheets("CustomFormats").Range("A5000").End(XlDirection.xlUp).Address).Row
    lRowLast_B = Worksheets("CustomFormats").Range( _
               Worksheets("CustomFormats").Range("B5000").End(XlDirection.xlUp).Address).Row
    For lrowno = 2 To lRowLast_A
        If (FormatIsFound(lRowLast_B, Worksheets("CustomFormats").Range("A" & lrowno).Value) = False) Then
            Worksheets("CustomFormats").Range("C" & lCounter + 2).Value = _
               Worksheets("CustomFormats").Range("A" & lrowno).Value

            If (Worksheets("CustomFormats").Range("A" & lrowno).Value = 0) Then
                Worksheets("CustomFormats").Range("C" & lCounter + 2).NumberFormatLocal = _
                   Worksheets("CustomFormats").Range("A" & lrowno).NumberFormatLocal
            Else
                If (ApplyNumberFormat(Worksheets("CustomFormats").Range("C" & lCounter + 2), _
                                      Worksheets("CustomFormats").Range("A" & lrowno).Value) = False) Then
                    Worksheets("CustomFormats").Range("C" & lCounter + 2).Interior.Color = RGB(255, 91, 91)
                End If

                Worksheets("CustomFormats").Range("C" & lCounter + 2).NumberFormatLocal = "General"
            End If

            lCounter = lCounter + 1
        End If
    Next lrowno
    lRowLast_C = Worksheets("CustomFormats").Range( _
                 Worksheets("CustomFormats").Range("C5000").End(XlDirection.xlUp).Address).Row
    Worksheets("CustomFormats").Range("C2:C" & lRowLast_C).Sort _
       Key1:=Worksheets("CustomFormats").Range("C2"), Order1:=xlAscending

'------------------ formats removed
    lRowLast_C = Worksheets("CustomFormats").Range( _
                 Worksheets("CustomFormats").Range("C5000").End(XlDirection.xlUp).Address).Row
    For lrowno = 2 To lRowLast_C
        If (DeleteNumberFormat(Range("C" & lrowno).Value) = True) Then
            Range("D" & lTotalRemoved + 2).Value = Range("C" & lrowno).Value
            lTotalRemoved = lTotalRemoved + 1
        Else
            If (Range("C" & lrowno).Interior.Color <> RGB(255, 91, 91)) Then
                Range("C" & lrowno).Interior.Color = RGB(146, 208, 80)
            End If
        End If
    Next lrowno
    lRowLast_D = Worksheets("CustomFormats").Range( _
                 Worksheets("CustomFormats").Range("D5000").End(XlDirection.xlUp).Address).Row
    Worksheets("CustomFormats").Range("D2:D" & lRowLast_D).Sort _
       Key1:=Worksheets("CustomFormats").Range("D2"), Order1:=xlAscending
    
    Range("A1").Value = "Formats available"
    Range("B1").Value = "Formats used"
    Range("C1").Value = "Formats not used"
    Range("D1").Value = "Formats removed"
    Range("A1:D1").Font.Bold = True
    Columns("A:D").ColumnWidth = 35
    Columns("A:D").HorizontalAlignment = xlLeft
    Range("A2").Select
    ActiveWindow.FreezePanes = True
    
    Call ConfirmRemoval(lTotalRemoved)
    
    Set wsh = Nothing
    Exit Sub
ErrorHandler:
    Set wsh = Nothing
    Call MsgBox(Err.Description)
End Sub

Private Function ApplyNumberFormat(ByVal oRange As Excel.Range, _
                                   ByVal sNumberFormat As String) As Boolean
    On Error GoTo ErrorHandler:
    oRange.NumberFormatLocal = sNumberFormat
    ApplyNumberFormat = True
    Exit Function
ErrorHandler:
    ApplyNumberFormat = False
End Function
                                   

Private Function FormatIsFound(ByVal lRowLast As Long, _
                               ByVal sNumberFormat As String) As Boolean Dim svalue As String
    On Error GoTo ErrorHandler:
    svalue = Application.WorksheetFunction.Match(sNumberFormat, _
                Worksheets("CustomFormats").Range("B2:B" & lRowLast), 0)
    FormatIsFound = True
    Exit Function
ErrorHandler:
    FormatIsFound = False
End Function

Private Function DeleteNumberFormat(ByVal sNumberFormat As String) As Boolean
    On Error GoTo ErrorHandler:
    Call ActiveWorkbook.DeleteNumberFormat(sNumberFormat)
    DeleteNumberFormat = True
    Exit Function
ErrorHandler:
    DeleteNumberFormat = False
End Function

Private Function AskForConfirmation() As Boolean Dim iResult As VBA.VbMsgBoxResult
    iResult = MsgBox("Do you want to delete unused custom formats from the workbook?", vbYesNo + vbQuestion)
    If (iResult = vbNo) Then AskForConfirmation = False
    If (iResult = vbYes) Then AskForConfirmation = True End Function

Private Sub ConfirmRemoval(ByVal lTotalRemoved As Long)
    Call MsgBox( _
       "'" & lTotalRemoved & "' number formats have been removed." & _
       vbCrLf & vbCrLf & _
       "The new 'CustomFormats' worksheet provides more information." & _
       vbCrLf & vbCrLf & _
       "The number formats that have been removed have been shaded in column 'C'.", _
       vbInformation + vbOKOnly)
End Sub

Private Function GetListOfNumberFormats(ByVal oRange As Excel.Range, _
                                        Optional ByVal bFromWorksheet As Boolean = False) As Variant Dim aFormatsArray() As Variant Dim sFormat As String, sSaveFormat As String Dim lCounter As Long, lRowLast As Long, lrowno As Long

    On Error GoTo ErrorHandler:
    ReDim aFormatsArray(0 To 2000)
    
    If (bFromWorksheet = True) Then
        lRowLast = Worksheets("CustomFormats").Range( _
                   Worksheets("CustomFormats").Range("A5000").End(XlDirection.xlUp).Address).Row
        For lrowno = 2 To lRowLast
           aFormatsArray(lrowno - 2) = Worksheets("CustomFormats").Range("A" & lrowno).Value
        Next lrowno
        lCounter = lrowno - 1
    Else
        oRange.Select
        aFormatsArray(0) = oRange.NumberFormatLocal
        lCounter = 1
        Do
            sSaveFormat = oRange.NumberFormatLocal
            sFormat = oRange.NumberFormatLocal
            VBA.DoEvents
            SendKeys "{tab 3}{down}{enter}"
            Application.Dialogs(xlDialogFormatNumber).Show sFormat
            aFormatsArray(lCounter) = Range("A2").NumberFormatLocal
            lCounter = lCounter + 1
        Loop Until aFormatsArray(lCounter - 1) = sSaveFormat
    End If
    
    ReDim Preserve aFormatsArray(0 To lCounter - 2)
    GetListOfNumberFormats = aFormatsArray
    Exit Function
ErrorHandler:
   Call MsgBox(Err.Message)
End Function

Remove Excess Shading

Sub ClearExcessRowsAndColumns() 
    Dim ar As Range
    Dim r As Double
    Dim c As Double
    Dim tr As Double
    Dim tc As Double
    Dim wksWks As Worksheet
    Dim ur As Range
    Dim arCount As Integer
    Dim i As Integer
    Dim blProtCont As Boolean
    Dim blProtScen As Boolean
    Dim blProtDO As Boolean
    Dim shp As Shape
    
    On Error GoTo ErrorHandler
    
' Application.ScreenUpdating = False
    For Each wksWks In ActiveWorkbook.Worksheets
      Err.Clear
'Store worksheet protection settings and unprotect if protected.
      blProtCont = wksWks.ProtectContents
      blProtDO = wksWks.ProtectDrawingObjects
      blProtScen = wksWks.ProtectScenarios
      wksWks.Unprotect ""
      
      If Err.Number = 1004 Then
         Err.Clear
         MsgBox "'" & wksWks.Name & "' is protected with a password and cannot be checked.", vbInformation
      Else
         Application.StatusBar = "Checking " & wksWks.Name & ", Please Wait..."
         r = 0
         c = 0

'Determine if the sheet contains both formulas and constants
         Set ur = Union(wksWks.UsedRange.SpecialCells(xlCellTypeConstants), wksWks.UsedRange.SpecialCells(xlCellTypeFormulas))
'If both fails, try constants only
         If Err.Number = 1004 Then
            Err.Clear
            Set ur = wksWks.UsedRange.SpecialCells(xlCellTypeConstants)
         End If
'If constants fails then set it to formulas
         If Err.Number = 1004 Then
            Err.Clear
            Set ur = wksWks.UsedRange.SpecialCells(xlCellTypeFormulas)
         End If
'If there is still an error then the worksheet is empty
         If Err.Number <> 0 Then
            Err.Clear
            If wksWks.UsedRange.Address <> "$A$1" Then
               ur.EntireRow.Delete
            Else
               Set ur = Nothing
            End If
         End If
'On Error GoTo 0
         If Not ur Is Nothing Then
            arCount = ur.Areas.Count
'determine the last column and row that contains data or formula
            For Each ar In ur.Areas
               i = i + 1
               tr = ar.Range("A1").Row + ar.Rows.Count - 1
               tc = ar.Range("A1").Column + ar.Columns.Count - 1
               If tc > c Then c = tc
               If tr > r Then r = tr
           Next
'Determine the area covered by shapes
'so we don't remove shading behind shapes
            For Each shp In wksWks.Shapes
               tr = shp.BottomRightCell.Row
               tc = shp.BottomRightCell.Column
               If tc > c Then c = tc
               If tr > r Then r = tr
            Next
            Application.StatusBar = "Clearing Excess Cells in " & wksWks.Name & ", Please Wait..."
            Set ur = wksWks.Rows(r + 1 & ":" & wksWks.Rows.Count)
'Reset row height which can also cause the lastcell to be innacurate
               ur.EntireRow.RowHeight = wksWks.StandardHeight
                ur.Clear

            Set ur = wksWks.Columns(ColLetter(c + 1) & ":" & ColLetter(wksWks.Columns.Count))
'Reset column width which can also cause the lastcell to be innacurate
                ur.EntireColumn.ColumnWidth = wksWks.StandardWidth
                ur.Clear
         End If
      End If
'Reset protection.
      wksWks.Protect "", blProtDO, blProtCont, blProtScen
      Err.Clear
    Next
    Application.StatusBar = False
' Application.SendKeys "%(oe)~{TAB}~"

    Application.CommandBars.ExecuteMso "PicturesCompress"
    Application.ScreenUpdating = True
    Exit Sub
ErrorHandler:

End Sub

Styles

Styles apply to a single workbook and cannot be easily transferred to other workbooks.


Selection.Style = "Normal" 

ActiveWorkbook.Styles.Add(Name:="your style name") 
ActiveWorkBook.Styles("your style name").Font.Name = "Arial"


Public Sub DeleteStyles() 
Dim objStyle As Style
Dim iReturn As Integer

   For Each objStyle In ActiveWorkbook.Styles
      If (objStyle.BuiltIn = False) Then
         iReturn = MsgBox("Do you want to delete this style: """ & objStyle.Name & """ ?", vbYesNo)
         If (iReturn = vbYes) Then
            objStyle.Delete
         End If
      End If
   Next objStyle
End Sub

AutoFormat


objRange.AutoFormat.Format:=xlRangeAutoFormatNone, _ 
                  Number:=True
                  Font:=True
                  Alignment:=
                  Border:=True
                  Pattern:=True
                  Width:=

Themes


ActiveWorkbook.Theme.ThemeColorScheme.Load("C:\temp\mytheme.xml") 

Debug.Print ActiveWorkbook.Theme.ThemeFontScheme.MajorFont(msoFontLanguageIndex.msoThemeLatin).Name 
Debug.Print ActiveWorkbook.Theme.ThemeFontScheme.MinorFont(msoFontLanguageIndex.msoThemeLatin).Name

Text To Columns

Parses a column of cells that contain text into several columns.


expression.TextToColumns(Destination, _ 
                         DataType:=xlTextParsingType.xlDemilited, _
                         TextQualifier:=xlTextQualifier.xlTextQualifierDoubleQuote, _
                         ConsecutiveDelimiter, _
                         Tab, _
                         Semicolon, _
                         Comma, _
                         Space, _
                         Other, _
                         OtherChar, _
                         FieldInfo:=xlColumnDataType., _
                         DecimalSeparator, _
                         ThousandsSeparator, _
                         TrailingMinusNumbers)

expression - Required.
Destination - Optional Variant. A Range object that specifies where Microsoft Excel will place the results. If the range is larger than a single cell, the top left cell is used.
ConsecutiveDelimiter - Optional Variant. True to have Microsoft Excel consider consecutive delimiters as one delimiter. The default value is False.
Tab - Optional Variant. True to have DataType be xlDelimited and to have the tab character be a delimiter. The default value is False.
Semicolon - Optional Variant. True to have DataType be xlDelimited and to have the semicolon be a delimiter. The default value is False.
Comma - Optional Variant. True to have DataType be xlDelimited and to have the comma be a delimiter. The default value is False.
Space - Optional Variant. True to have DataType be xlDelimited and to have the space character be a delimiter. The default value is False.
Other - Optional Variant. True to have DataType be xlDelimited and to have the character specified by the OtherChar argument be a delimiter. The default value is False.
OtherChar - Optional Variant (required if Other is True). The delimiter character when Other is True. If more than one character is specified, only the first character of the string is used; the remaining characters are ignored.
FieldInfo - Optional Variant. An array containing parse information for the individual columns of data. The interpretation depends on the value of DataType. When the data is delimited, this argument is an array of two-element arrays, with each two-element array specifying the conversion options for a particular column. The first element is the column number (1-based), and the second element is one of the constants specifying how the column is parsed.
The column specifiers can be in any order. If a given column specifier is not present for a particular column in the input data, the column is parsed with the General setting. This example causes the third column to be skipped, the first column to be parsed as text, and the remaining columns in the source data to be parsed with the General setting.
Array(Array(3, 9), Array(1, 2))


If the source data has fixed-width columns, the first element of each two-element array specifies the starting character position in the column (as an integer; 0 (zero) is the first character). The second element of the two-element array specifies the parse option for the column as a number from 1 through 9, as listed above.


The following example parses two columns from a fixed-width file, with the first column starting at the beginning of the line and extending for 10 characters. The second column starts at position 15 and goes to the end of the line. To avoid including the characters between position 10 and position 15, Microsoft Excel adds a skipped column entry.


Array(Array(0, 1), Array(10, 9), Array(15, 1))


DecimalSeparator Optional String. The decimal separator that Microsoft Excel uses when recognizing numbers. The default setting is the system setting.
ThousandsSeparator Optional String. The thousands separator that Excel uses when recognizing numbers. The default setting is the system setting.
TrailingMinusNumbers Optional Variant. Numbers that begin with a minus character.



Example

This example converts the contents of the Clipboard, which contains a space-delimited text table, into separate columns on Sheet1. You can create a simple space-delimited table in Notepad or WordPad (or another text editor), copy the text table to the Clipboard, switch to Microsoft Excel, and then run this example.


Worksheets("Sheet1").Activate 
ActiveSheet.Paste
Selection.TextToColumns DataType:=xlDelimited, _
    ConsecutiveDelimiter:=True, Space:=True

Application.DisplayPageBreaks

This property controls if page breaks (both automatic and manual) on the specified worksheet are displayed.


Application.PrintCommunication = False

This was added in Excel 2010
ActiveSheet.PageSetup.
Means the printer is only contacted once


Displaying the Workbook in Print Preview

ActiveWorkBook.PrintPreview 


Displaying the Workbook in Page Break View

ActiveWindow.View = xlPageBreakPreview 
ActiveWindow.View = xlNormalView

PageSetup Object

Represents the page setup description. The PageSetup object contains all page setup attributes (left margin, bottom margin, paper size, and so on) as properties.


Using the PageSetup Object
Use the PageSetup property to return a PageSetup object. The following example sets the orientation to landscape mode and then prints the worksheet.


With Worksheets("Sheet1") 
    .PageSetup.Orientation = xlLandscape
    .PrintOut
End With


PrintPreview Method

Shows a preview of the object as it would look when printed.
This example displays Sheet1 in print preview.

Worksheets("Sheet1").PrintPreview 


PrintArea Property

Returns or sets the range to be printed, as a string using A1-style references in the language of the macro. Read/write String.
Set this property to False or to the empty string ("") to set the print area to the entire sheet.
This property applies only to worksheet pages.


This example sets the print area to cells A1:C5 on Sheet1.

Worksheets("Sheet1").PageSetup.PrintArea = "$A$1:$C$5" 

This example sets the print area to the current region on Sheet1. Note that you use the Address property to return an A1-style address.


Worksheets("Sheet1").Activate 
ActiveSheet.PageSetup.PrintArea = ActiveCell.CurrentRegion.Address


PrintOut Method

expression.PrintOut( [ From, To, Copies, Preview, ActivePrinter, PrintToFile, Collate, PrToFileName ])
expression Required. An expression that returns an object in the Applies To list.


From - (Variant) The number of the page at which to start printing. If this argument is omitted, printing starts at the beginning.
To - (Variant) The number of the last page to print. If this argument is omitted, printing ends with the last page.
Copies (Variant) The number of copies to print. If this argument is omitted, one copy is printed.
Preview (Variant) True to have Microsoft Excel invoke print preview before printing the object. False (or omitted) to print the object immediately.
ActivePrinter (Variant) Sets the name of the active printer.
PrintToFile (Variant) True to print to a file. If PrToFileName is not specified, Microsoft Excel prompts the user to enter the name of the output file.
Collate (Variant) True to collate multiple copies.
PrToFileName (Variant) If PrintToFile is set to True, this argument specifies the name of the file you want to print to.


BeforePrint Event

Include the folder path and workbook name in a header

Private Sub Workbook_BeforePrint(Cancel As Boolean) 
Dim objwsh As Worksheet
   For Each objwsh In ThisWorkbook.Sheets
      objwsh.PageSetup.LeftHeader = ThisWorkbook.FullName
   Next objwsh
End Sub

Remarks

Pages in the descriptions of From and To refers to printed pages - not overall pages in the sheet or workbook.


This example prints the active sheet.

ActiveSheet.PrintOut 

Printing a Workbook

Workbooks("Book2.xls").PrintOut 
ThisWorkbook.PrintOut(From, To, Copies)

Printing to a File

ActiveSheet.PrintOut PrintToFile:=Time, PrToFileName:="name of file.prn"             'Printing to a file  


Print to a network printer

The example macros below shows how to get the full network printer name (useful when the network printer name can change) and print a worksheet to this printer:


Sub PrintToNetworkPrinterExample() 
Dim strCurrentPrinter As String, strNetworkPrinter As String
    strNetworkPrinter = GetFullNetworkPrinterName("HP LaserJet 8100 Series PCL")
    If Len(strNetworkPrinter) > 0 Then ' found the network printer
        strCurrentPrinter = Application.ActivePrinter
' change to the network printer
        Application.ActivePrinter = strNetworkPrinter
        Worksheets(1).PrintOut ' print something
' change back to the previously active printer
        Application.ActivePrinter = strCurrentPrinter
    End If
End Sub

Function GetFullNetworkPrinterName(strNetworkPrinterName As String) As String
' returns the full network printer name
' returns an empty string if the printer is not found
' e.g. GetFullNetworkPrinterName("HP LaserJet 8100 Series PCL")
' might return "HP LaserJet 8100 Series PCL on Ne04:"
Dim strCurrentPrinterName As String, strTempPrinterName As String, i As Long
    strCurrentPrinterName = Application.ActivePrinter
    i = 0
    Do While i < 100
        strTempPrinterName = strNetworkPrinterName & " on Ne" & Format(i, "00") & ":"
        On Error Resume Next ' try to change to the network printer
        Application.ActivePrinter = strTempPrinterName
        On Error GoTo 0
        If Application.ActivePrinter = strTempPrinterName Then
' the network printer was found
            GetFullNetworkPrinterName = strTempPrinterName
            i = 100 ' makes the loop end
        End If
        i = i + 1
    Loop
' remove the line below if you want the function to change the active printer
    Application.ActivePrinter = strCurrentPrinterName ' change back to the original printer
End Function

Change the default printer

This example macro shows how to print a selected document to another printer then the default printer. This is done by changing the property Application.ActivePrinter:


Sub PrintToAnotherPrinter() 
Dim strCurrentPrinter As String
    strCurrentPrinter = Application.ActivePrinter ' store the current active printer
    On Error Resume Next ' ignore printing errors
    Application.ActivePrinter = "microsoft fax on fax:" ' change to another printer
    ActiveSheet.PrintOut ' print the active sheet
    Application.ActivePrinter = strCurrentPrinter ' change back to the original printer
    On Error Goto 0 ' resume normal error handling
End Sub

Identify Default Printer

Private Declare Function GetProfileStringA Lib "kernel32" (ByVal lpAppName As String, ByVal lpKeyName As String, ByVal lpDefault As String,  ByVal lpReturnedString As String, ByVal nSize As Long) As Long 

Sub DefaultPrinterInfo()
    Dim strLPT As String * 255
    Dim Result As String
    Call GetProfileStringA _
       ("Windows", "Device", "", strLPT, 254)
    
    Result = Application.Trim(strLPT)
    ResultLength = Len(Result)

    Comma1 = Application.Find(",", Result, 1)
    Comma2 = Application.Find(",", Result, Comma1 + 1)

' Gets printer's name
    Printer = Left(Result, Comma1 - 1)

' Gets driver
    Driver = Mid(Result, Comma1 + 1, Comma2 - Comma1 - 1)

' Gets last part of device line
    Port = Right(Result, ResultLength - Comma2)

' Build message
    Msg = "Printer:" & Chr(9) & Printer & Chr(13)
    Msg = Msg & "Driver:" & Chr(9) & Driver & Chr(13)
    Msg = Msg & "Port:" & Chr(9) & Port

' Display message
    MsgBox Msg, vbInformation, "Default Printer Information"
End Sub

Printing to PDF

Range("B2:O37").PrintOut 

ActiveWorkbook.ExportAsFixedFormat 
ActiveSheet.ExportAsFixedFormat _

Dim cht As Chart 
Set cht = ws.ChartObjects("Chart 1").Chart
cht.ExportAsFixedFormat

Saving a Range as PDF

Private Sub Range_SaveAsPDF 
   Call Range.ExportAsFixedFormat( _
      Type:=xlFixedFormatType.xlTypePDF, _
      Filename:="C:\Temp\FileName", _
      Quality:=xlFixedFormatQuality.xlQualityStandard, _
      IncludeDocProperties:=True, _
      IgnorePrintAreas:=False, _
      OpenAfterPublish:=True)
End Sub

Type - Can be either xlTypePDF or xlTypeXPS
Filename - A string that indicates the name of the file to be saved. You can include a full path, or Excel saves the file in the current folder.
Quality - Can be set to either xlQualityStandard or xlQualityMinimum.
IncludeDocProperties - Set to True to indicate that document properties should be included, or set to False to indicate that they are omitted.
IgnorePrintAreas - If set to True, ignores any print areas set when publishing. If set to False, uses the print areas set when publishing.
OpenAfterPublish - If set to True, displays the file in the viewer after it is published. If set to False, the file is published but not displayed.
From - The number of the page at which to start publishing. If this argument is omitted, publishing starts at the beginning.
To - The number of the last page to publish. If this argument is omitted, publishing ends with the last page.
FixedFormatExtClassPtr - Pointer to the FixedFormatExt class.


Defining Print Area

The following two lines are equivalent

Activesheet.PageSetup.PrintArea = "" 
Activesheet.Names("Print Area").Delete

Activesheet.VPageBreaks(1).Location = Worksheets(1).Range("B5") 
Activesheet.VPageBreaks(1).DragOff Direction:=xlDirection.xlToRight RegionIndex:=1

VPageBreaks Collection

A collection of vertical page breaks within the print area.
Each vertical page break is represented by a VPageBreak object
Use the Add method to add a vertical page break.


Activesheet.VPageBreaks.Add Before:=ActiveCell 

If you add a page break that does not intersect the print area, then the new VPageBreak object will not appear in the VPageBreaks collection for that sheet.


For an automatic print area, the VPageBreaks property applies only to the page breaks within the print area.


For a user-defined print area of the same range, the VPageBreaks property applies to all the page breaks.


VPageBreaks(1).DragOff (Direction, RegionIndex)

Direction - The direction to drag the page break
RegionIndex - The print area region index for the page break.If the print area is continuous then there is only one print region. If the print area is non continous then there is more than one.


This method drags a page break off the print area.
You have to be in print preview mode for this to work
If you are not in page page preview then an error will be generated.

ActiveWindow.View = xlPageBreakPreview 
Activesheet.VPageBreaks(1).DragOff Direction:=xlDirection.xlToRight RegionIndex:=1
ActiveWindow.View = xlNormalView

HPageBreaks Collection


Whenever you use / change the print area of a worksheet by dragging the blue lines in "page break" view, using activesheet.Hpagebreaks(1).dragoff direction, regionindex you will get a Dr Watson if the page breaks to does not exist.


How many pages will be printed ?

To determine the number of pages that will be printed for the active worksheet use:
This is an XLM (Excel 4) macro.

Public Sub ShowPageCount() 
Dim ipagecount As Integer
Dim ipages As Integer
Dim objwsh as Worksheet

   ipagecount = 0
   For Each objwsh In Worksheets
      objwsh.Activate
      ipages = ExecuteExcel4Macro("Get.Document(50)")
      ipagecount = ipagecount + ipages
   Next objwsh
End Sub

PageSetup - Page tab

With ActiveSheet.PageSetup 
    .Orientation = xlPageOrientation.xlLandscape
    .Zoom = 100
    .FitToPagesWide = 1
    .FitToPagesTall = 1
    .FitToPagesTall = False ' Automatic
    .PaperSize = xlPaperSize.xlPaperA4
    .PrintQuality = 300
    .FirstPageNumber = Constants.xlAutomatic | 5
End With

PageSetup - Margins tab

Margins are set or returned in Points.
The units that are displayed on the Page Setup dialog box are inches although the units accepted for the following properties are Points.
How can you define 0.5 (or the smallest margins) for all margins ??

With ActiveSheet.PageSetup 
    .LeftMargin = Application.InchesToPoints(0.75)
    .RightMargin = Application.InchesToPoints(0.75)
    .TopMargin = Application.InchesToPoints(1)
    .BottomMargin = Application.InchesToPoints(1)
    .HeaderMargin = Application.InchesToPoints(0.5)
    .FooterMargin = Application.InchesToPoints(0.5)
    .CenterHorizontally = False
    .CenterVertically = False
End With

You can use the following conversion functions to help convert between the various units.

ActiveSheet.PageSetup.LeftMargin = Application.CentimetersToPoints(1.9) 
ActiveSheet.PageSetup.LeftMargin = Application.MillimetersToPoints(1.9)
ActiveSheet.PageSetup.LeftMargin = Application.InchesToPoints(1.9)

For more details, please refer to the Measurements page.


PageSetup - Header and Footer tab

This is from the Header/Footer tab of the Page Setup dialog box.

With ActiveSheet.PageSetup 
    .LeftHeader = ""
    .CenterHeader = ""
    .RightHeader = ""
    .LeftFooter = ""
    .CenterFooter = ""
    .RightFooter = ""
End With

In Excel 2002 you can include the full file path in a custom header or footer

ActiveSheet.Pagesetup.CenterFooter = ActiveWorkbook.FullName 
Worksheets(1).PageSetup.CenterFooter = ActiveWorkbook.FullName

It is possible to write code to insert a page header in the centre position although the CenterHeader property (as well as the other Header and Footer properties) are not very helpful.
These should be objects but do not appear to be ??


ActiveSheet.PageSetup.CenterHeader = &""Arial,Bold Italic""&11Better Solutions" 

PageSetup - Sheet tab

With ActiveSheet.PageSetup 
    .PrintArea = "$B$2:$D$20"
'defining the print area automatically displays page break lines on the worksheet
'these can be hidden using the following line: ActiveSheet.DisplayAutomaticPageBreaks = False

    .PrintTitleRows = "$B$2:$D$20"
    .PrintTitleColumns = ""
    .PrintGridlines = False
    .BlackAndWhite = False
    .Draft = False
    .PrintHeadings = False
    .PrintComments = xlPrintLocation.xlPrintNoComments
    .PrintErrors = xlPrintErrors.xlPrintErrorsDisplayed
    .Order = xlOrder.xlDownThenOver
End With

Header and Footer

This example prints the workbook name and page number at the bottom of each page.
Worksheets("Sheet1").PageSetup.CenterFooter = "&F page &P"
This example prints the date and page number at the top of each page.
Worksheets("Sheet1").PageSetup.CenterHeader = "&D page &P of &N"


Header and Footer - Graphic Object

Contains properties that apply to header and footer picture objects.


Using the Graphic object
There are several properties of the PageSetup object that return the Graphic object.


Use the CenterFooterPicture, CenterHeaderPicture, LeftFooterPicture, LeftHeaderPicture, RightFooterPicture, or RightHeaderPicture properties to return a Graphic object.


CenterFooterPicture - Returns a Graphic object that represents the picture for the center section of the footer. Used to set attributes about the picture.
The CenterFooterPicture property is read-only, but the properties on it are not all read-only.


The following example adds a picture titled: Sample.jpg from the C:\ drive to the left section of the footer. This example assumes that a file called Sample.jpg exists on the C:\ drive.


Sub InsertPicture() 

    With ActiveSheet.PageSetup.LeftFooterPicture
        .FileName = "C:\Sample.jpg"
        .Height = 275.25
        .Width = 463.5
        .Brightness = 0.36
        .ColorType = msoPictureGrayscale
        .Contrast = 0.39
        .CropBottom = -14.4
        .CropLeft = -28.8
        .CropRight = -14.4
        .CropTop = 21.6
    End With

' Enable the image to show up in the left footer.
    ActiveSheet.PageSetup.LeftFooter = "&G"

End Sub

Note It is required that "&G" is a part of the LeftFooter string in order for the image to show up in the left footer.


Prevent Users From Printing

Private Sub Workbook_BeforePrint(Cancel As Boolean) 
   Cancel = True
   Call MsgBox("You are not allowed to print this workbook.", vbInformation + vbOKOnly)
End Sub

Prevent Certain Sheets

You could still select a different worksheet and then print the whole workbook ??

Private Sub Workbook_BeforePrint(Cancel As Boolean) 
   Select Case ActiveSheet.Name
      Case "Sheet1", "Sheet2"
         Cancel = True
         Call MsgBox("You are not allowed to print this particular worksheet.", vbInformation + vbOKOnly)
   
   End Select
End Sub

© 2026 Better Solutions Limited. All Rights Reserved. © 2026 Better Solutions Limited TopPrev