Excel VBA Overview¶
Gallery¶
type: folder_brief_live
Contents¶
- VBA - Notes
- VBA - Refresh All
- VBA - Unhide All Worksheets
- VBA - Useful Utilities
- VBA - Optimize Speed
- VBA - Unhide all Rows and Columns
- VBA - SQL Stored Procedure Caller Module
- VBA - Save All
- VBA - File Dialog
- VBA - Page Setup and Print Macros
- VBA - Module Template
- VBA - Make All Open Files Read Only
- VBA - ListLinks Module
- VBA - Balloon Notification
- VBA - Copy Module from one Workbook to Another
- VBA - Create and Run a SQL Query
- VBA - Check for Broken Links in Workbook
- VBA - Alert
VBA - Notes¶
VBA Notes¶
*Source: *
- Example Sub Procedure
'The Sub statement (Note: All procedures are public by default)
Sub SubExample()
  'The instructions
  'On Error GoTo Err_Hanlder
  With Selection.Font 
    'Set font color property
    .Color = wdColorRed 
    'Set font size property
    .Size = 14 
  End With
  'The Exit statement
  Exit Sub
Err_Handler:
'The End statement
End Sub 
The Exit Sub statement typically precedes any error handling code statements. For more on error handling see my: Error Handling 101
A Sub procedure can take “parameters”, such as constants, variables, or expressions that are passed to it as “arguments” by another “calling” procedure.
The following is an example of a Sub that takes parameters passed as arguments from a calling procedure:
Sub Main()
 'Other code could go here
  'Call and pass arguments to another sub
  'Property values for font color _
  and size are passed as arguments  FormatFontAtSelection Selection.Range, wdColorRed, 14 
  'Other code could go here lbl_Exit:
  Exit Sub
End Sub
Sub FormatFontAtSelection(ByRef oRng As Range, oColor As Long, oSize As Long) 'Parameters
  With oRng.Font
    .Color = oColor
    .Size = oSize
  End With
lbl_Exit:
  Exit Sub
End Sub
- Function Procedure: A Function procedure is a series of Visual Basic statements enclosed by the Function and End Function statements.
- It is similar to a Sub procedure, but a function can also return a value.
- A function can take arguments, such as constants, variables, or expressions that are passed to it by a calling procedure.
- If a Function procedure has no arguments, its Function statement must include an empty set of parentheses.
- A function returns a value by assigning a value to its name in one or more statements of the procedure.
Appendix: Links¶
Backlinks:
list from [[VBA Notes]] AND -"Changelog"
VBA - Useful Utilities¶
- 
VBA - Useful Utilities¶
*Source: *
## Workbook Functions
'Returns TRUE if a given workbook reference exists and has not been saved
Public Function WBNotSaved(TargetWB As Workbook) As Boolean
    On Error Resume Next
    If TargetWB Is Nothing Then Exit Function
    If Len(TargetWB.Path) > 0 Then Exit Function
    WBNotSaved = Len(TargetWB.Path) = 0
End Function
'Returns TRUE if a given workbook reference is unused. This indicates that the workbook was unexpectedly closed
Public Function WBNullRef(TargetWB As Workbook) As Boolean
    On Error Resume Next
    If TargetWB Is Nothing Then Exit Function
    If Len(TargetWB.Name) = 0 Then
        WBNullRef = Not (Err.Number = 0)
        Err.Clear
    End If
End Function
### FindWorkbook()
'Returns a workbook object based on a matching name search
Public Function FindWorkbook(ByVal WorkbookName As String) As Workbook
    If Len(WorkbookName) = 0 Then Exit Function
    Dim Index As Long
    For Index = 1 To Workbooks.Count
        If Workbooks(Index).Name Like "*" & WorkbookName & "*" Then
            Set FindWorkbook = Workbooks(Index)
            Exit Function
        End If
    Next Index
End Function
### IsWorkBookOpen()
'Returns boolean if a given workbook is currently open
Public Function IsWorkBookOpen(ByVal WorkbookName As String) As Boolean
    On Error GoTo ErrorHandler
    If Len(WorkbookName) = 0 Then Exit Function
    Dim WBO As Workbook: Set WBO = Workbooks(WorkbookName)
    IsWorkBookOpen = Not WBO Is Nothing
ErrorHandler:
    Set WBO = Nothing
End Function
### IsWorkbookProtected
'WORKBOOK FUNCTIONS
'Returns boolean if a given workbook is password protected
Public Function IsWBProtected(ByRef TWB As Workbook) As Boolean
    If TWB Is Nothing Then Exit Function
    IsWBProtected = TWB.ProtectWindows Or TWB.ProtectStructure
End Function
## Worksheet Functions
### GetSheet()
'WORKSHEET FUNCTIONS
'Returns a worksheet with the given name, creates a new one if it doesn't already exist
Public Function GetSheet(SheetName As String, Optional WB As Workbook, Optional ForceNew As Boolean) As Worksheet
    On Error Resume Next
    If Len(SheetName) = 0 Then Exit Function
    If WB Is Nothing Then Set WB = ThisWorkbook
    Set GetSheet = WB.Worksheets(Left(SheetName, 31)) 'Test if the given named worksheet exists
    If ForceNew Then
        Dim Append As String, MatchCounter As Long
        If Not GetSheet Is Nothing Then 'If the given named worksheet exists, then begin appending the default ' (N)' postfix
            Do Until GetSheet Is Nothing
                Append = " (" & MatchCounter & ")"
                Set GetSheet = Nothing
                Set GetSheet = WB.Worksheets(Left(SheetName, 31 - Len(Append)) & Append)
                MatchCounter = MatchCounter + 1
            Loop
        End If
        Set GetSheet = WB.Worksheets.Add(After:=WB.Worksheets(WB.Worksheets.Count))
        GetSheet.Name = Left(SheetName, 31 - Len(Append)) & Append
    Else
        If GetSheet Is Nothing Then 'If the given name does not exist, create a worksheet with the given name
            Set GetSheet = WB.Worksheets.Add(After:=WB.Worksheets(WB.Worksheets.Count))
            GetSheet.Name = Left(SheetName, 31)
        End If
    End If
End Function
### SheetExists()
'Returns boolean if a given worksheet exists in a given workbook
Public Function SheetExists(ByVal SheetName As String, Optional ByRef WB As Workbook) As Boolean
    On Error Resume Next
    If WB Is Nothing Then Set WB = ThisWorkbook
    SheetExists = Not WB.Worksheets(SheetName) Is Nothing
End Function
### CleanSheetName()
'Sanitizes a given string to comply with Excel's Worksheet naming scheme
Public Function CleanSheetName(WorksheetName As String) As String
    CleanSheetName = WorksheetName
    Const InvalidChars As String = "\/?*[]"
    Dim Index As Long
    For Index = 1 To Len(InvalidChars)
        CleanSheetName = Replace(CleanSheetName, Mid(InvalidChars, Index, 1), "")
    Next Index
    CleanSheetName = Left(CleanSheetName, 31)
End Function
## Miscellaneous Functions
### ActiveRow()
'Returns the row number of the currently selected cell
Public Function ActiveRow() As Long
    ActiveRow = Application.ActiveCell.Row
End Function
### ActiveCol()
'Returns the column number of the currently selected cell
Public Function ActiveCol() As Long
    ActiveCol = Application.ActiveCell.Column
End Function
### CurrentCell()
Public Function CurrentCell() As Range
    Set CurrentCell = Application.Caller
End Function
### GetURL()
'Returns a URL within a given cell if it contains one
Public Function GetURL(Target As Range) As String
    If Target Is Nothing Then Exit Function
    'Grab URL if using the insert link method (Just the first one)
    If Target.Hyperlinks.Count > 0 Then
        GetURL = Target.Hyperlinks.Item(1).Address
        Exit Function
    End If
    'Grab URL if using the HYPERLINK formula
    If InStr(1, Target.Formula, "HYPERLINK(""", vbTextCompare) Then
        Dim SLeft As Long: SLeft = InStr(1, Target.Formula, "HYPERLINK(""", vbTextCompare)
        Dim SRight As Long: SRight = InStr(SLeft + 11, Target.Formula, """,""", vbTextCompare)
        GetURL = Mid(Target.Formula, SLeft + 11, SRight - (SLeft + 11))
    End If
End Function
## Appendix: Links
- Code
- Development
- Excel
- Microsoft Office
- Excel - VBA Backlinks:
list from [[VBA - Useful Utilities]] AND -"Changelog"
Code Snippets¶
VBA - Refresh All¶
VBA - Refresh All¶
*Source: *
Refresh all Workbook Connections, Pivot Tables, Charts, Forms and Formulas
Sub RefreshAll() 'Refresh All Workbook Connections, Pivot Tables, Charts, Forms and Formulas
    Dim conn As Variant
    Dim pvtTbl As PivotTable
    Dim pCache As PivotCache
    Dim myChart As ChartObject
    Dim obj As AccessObject
    Dim dbs As Object
    Dim intFormCount As Integer
    On Error GoTo ErrorHandler
    Call Functions.OptimizeCodeSpeed
    ActiveWorkbook.RefreshAll
    'Connections Refresh
        Application.CalculateUntilAsyncQueriesDone
        Application.CalculateFullRebuild
        Application.CalculateUntilAsyncQueriesDone
        For Each conn In ActiveWorkbook.Connections
            conn.ODBCConnection.BackgroundQuery = False
        Next conn
    'Refresh all pivot tables
        For Each pCache In ActiveWorkbook.PivotCaches
            pCache.Refresh
        Next pCache
        For Each pvtTbl In ActiveSheet.PivotTables
            pvtTbl.RefreshTable
        Next
    'Refresh all Workbook Charts
        For Each myChart In ActiveSheet.ChartObjects
            myChart.Chart.Refresh
        Next myChart
'Refresh Access Forms, it requieres: Tools > References > Microsoft Access
        Set dbs = Application.CurrentProject
        intFormCount = dbs.AllForms.Count - 1
        For i = 0 To intFormCount
            If dbs.AllForms(i).isloaded = True Then
                dbs.AllForms(i).Refresh
            End If
        Next
    'Refresh Workbook Links Sources
        ActiveWorkbook.UpdateLink Name:=ActiveWorkbook.LinkSources, Type:=xlExcelLinks
    ActiveWorkbook.RefreshAll
    Application.CalculateFullRebuild 'Refresh all formulas, including custom ones
ErrorHandler:
    Call Functions.OptimizeCodeSpeedRestore
    Exit Sub
End Sub
Appendix: Links¶
Backlinks:
list from [[VBA - Refresh All]] AND -"Changelog"
VBA - Unhide All Worksheets¶
- 
VBA - Unhide All Worksheets¶
Source: https://trumpexcel.com/excel-macro-examples/#Unhide-All-Worksheets-at-One-Go
'This code will unhide all sheets in the workbook
Sub UnhideAllWoksheets()
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
ws.Visible = xlSheetVisible
Next ws
End Sub
## Appendix: Links
- Code
- Development
- Excel
- Microsoft Office
- Excel - VBA Backlinks:
list from [[VBA - Unhide All Worksheets]] AND -"Changelog"
VBA - Optimize Speed¶
VBA - Optimize Speed¶
*Source: *
Contents¶
OptimizeVBA¶
Sub OptimizeVBA(isOn As Boolean)
    Application.Calculation = IIf(isOn, xlCalculationManual, xlCalculationAutomatic)
    Application.EnableEvents = Not (isOn)
    Application.ScreenUpdating = Not (isOn)
    ActiveSheet.DisplayPageBreaks = Not (isOn)
End Sub
OptimizeCodeSpeed¶
Public Sub OptimizeCodeSpeed()
  On Error Resume Next
    Application.EnableEvents = False
    Application.DisplayAlerts = False
    Application.ScreenUpdating = False
    Application.EnableAnimations = False
    ActiveSheet.DisplayPageBreaks = False
    Application.DisplayStatusBar = False
    Application.Calculation = xlCalculationManual
  On Error GoTo 0
End Sub
OptimizeCodeSpeedRestore¶
Public Sub OptimizeCodeSpeedRestore()
  On Error Resume Next
    Application.EnableEvents = True
    Application.DisplayAlerts = True
    Application.ScreenUpdating = True
    ActiveSheet.DisplayPageBreaks = False
    Application.DisplayStatusBar = True
    Application.Calculation = xlCalculationAutomatic
  On Error GoTo 0
End Sub
LudicrousMode¶
'Adjusts Excel settings for faster VBA processing
Public Sub LudicrousMode(ByVal Toggle As Boolean)
    Application.ScreenUpdating = Not Toggle
    Application.EnableEvents = Not Toggle
    Application.DisplayAlerts = Not Toggle
    Application.EnableAnimations = Not Toggle
    Application.DisplayStatusBar = Not Toggle
    Application.PrintCommunication = Not Toggle
    Application.Calculation = IIf(Toggle, xlCalculationManual, xlCalculationAutomatic)
End Sub
Example¶
Sub example()
    'Stop automatic calculation of excel cells
    Application.Calculation = xlCalculationManual
    'Stop screen updating
    Application.ScreenUpdating = False
    'Some code
    'Put it back to "normal"
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
End Sub
Appendix: Links¶
Backlinks:
list from [[VBA - Optimize Speed]] AND -"Changelog"
VBA - Unhide all Rows and Columns¶
VBA - Unhide all Rows and Columns¶
*Source: *
Appendix: Links¶
Backlinks:
list from [[VBA - Unhide all Rows and Columns]] AND -"Changelog"
VBA - SQL Stored Procedure Caller Module¶
- 
VBA - SQL Stored Procedure Caller Module¶
Source: https://gist.github.com/2bb551e24cb2fab4f61db673f6ee62a3#file-mdlgen_dbcommands-vb
Excel VBA - SQL Stored Procedure Caller Module - mdlGen_DBCommands.vb:
'This module was originally created by Rohan Shenoy in December 2012. It was designed to collect parameters,
'and use them to call stored procedures (in SQL Server 2005+). The primary function - sqlStoredProc takes the
'name of a stored procedure and a scripting dictionary containing a variable number of parameters (stored in
'key-value pairs). If the procedure returns a dataset, the function returns this data as an ADO recordset
'to the caller.
'
' - © R Shenoy 30/07/2013
'
'(Remember to add references to ADO and Scripting Runtime libraries to any workbooks that you add this to)
Option Explicit
'dictionary of parameters to pass to sqlStoredProc function when invoking SQL Server Stored Procedures
Public dicParams    As New Scripting.Dictionary
'Connection String to UK Apps DB (ExcelLogin user)
Public strConn              As String
Public Const strConnEnc     As String = "80;82;79;86;73;68;69;82;61;..."
'For obvious reasons I've not included the whole connection string here. You can use the Encode() function below to generate
'a (trivially) obfuscated version of the raw connection string so that passwords aren't in plain text. If you are concerned
'about securing your DB credentials, you probably want to password-protect the VBA project as well
'Recordset for global use
Public rs           As New ADODB.Recordset
Public Function sqlStoredProc(strStoredProc As String, dicParameters As Scripting.Dictionary)
'Run stored procedure and pass parameters - returns Nothing if no records found
'If stored proc expects a parameter not contained in dictionary, an error is returned.
'Any parameters not required by the proc will just be ignored.
'Requisites: strConn, strConnEnc, Decode()
    Dim conn        As ADODB.Connection
    Dim cmd         As ADODB.Command
    Dim rs          As New ADODB.Recordset
    Dim rs2         As New ADODB.Recordset
    Dim param       As ADODB.Parameter
    Dim dicTypes    As New Scripting.Dictionary
    'Define data type conversion from SQL to ADODB
    dicTypes("varchar") = adVarChar
    dicTypes("char") = adChar
    dicTypes("text") = adVarChar
    dicTypes("int") = adInteger
    dicTypes("datetime") = adDBTimeStamp
    dicTypes("numeric") = adNumeric
    dicTypes("nvarchar") = adVarChar
    dicTypes("decimal") = adDecimal
    dicTypes("date") = adDate
    dicTypes("bit") = adBoolean
    If strConn = "" Then strConn = Decode(strConnEnc)
    'Connect to database
    Set conn = New ADODB.Connection
    conn.Open strConn
    'Get parameter names, datatypes and precision for Stored Proc and store in rs2
    Set cmd = New ADODB.Command
    cmd.CommandText = "pGetSPParameters"
    cmd.CommandType = adCmdStoredProc
    cmd.ActiveConnection = conn
    Set param = cmd.CreateParameter("@SPName", adVarChar, adParamInput, 100, strStoredProc)
    cmd.Parameters.Append param
    With rs2
        .CursorType = adOpenStatic
        .CursorLocation = adUseClient
        .Open cmd
        'Now create command to call Stored Procedure
        Set cmd = New ADODB.Command
        cmd.CommandText = strStoredProc
        cmd.CommandType = adCmdStoredProc
        cmd.ActiveConnection = conn
        'Loop through each parameter required by the proc and add it to the ADO command
       ' On Error GoTo Closedown
        If Not (.BOF And .EOF) Then
            .MoveFirst
            Do While Not .EOF
                'If missing parameter not supplied then goto error handler
                If Not dicParameters.Exists(!ParameterName.Value) Then
                    GoTo InvalidParameter
                End If
                Set param = cmd.CreateParameter(!ParameterName.Value, _
                                                dicTypes(!DataType.Value), _
                                                adParamInput, _
                                                !CharacterMaxLength.Value, _
                                                dicParameters(!ParameterName.Value))
                If !NumericScale > 0 Then param.NumericScale = !NumericScale.Value
                If !NumericPrecision > 0 Then param.Precision = !NumericPrecision.Value
                cmd.Parameters.Append param
                .MoveNext
            Loop
        End If
    End With
    Set rs = New ADODB.Recordset
    With rs
        .CursorType = adOpenStatic
        .CursorLocation = adUseClient
        '.LockType = adLockOptimistic
        .Open cmd
    End With
    Set sqlStoredProc = Nothing
    If rs.State = 0 Then
        'Set rs = Nothing
    ElseIf rs.BOF And rs.EOF Then
        'Set rs = Nothing
    Else
        Set rs.ActiveConnection = Nothing
        Set cmd = Nothing
        Set conn = Nothing
        Set sqlStoredProc = rs
    End If
    GoTo Closedown
InvalidParameter:
    MsgBox "Procedure " & strStoredProc & " is missing parameter " & rs2!ParameterName
    Set cmd = Nothing
Closedown:
    If Err.Number <> 0 Then
        MsgBox "Error - " & Err.Description
    End If
    'Close all objects
    On Error Resume Next
    rs2.Close
    'conn.Close
    Set rs2 = Nothing
    'Set conn = Nothing
    Set cmd = Nothing
    On Error GoTo 0
End Function
Function TestConnection() As Boolean
'Simple function to test db connection
'Requisites: strConn, Decode
    Dim cnTest              As ADODB.Connection
    Set cnTest = New ADODB.Connection
    If strConn = "" Then strConn = Decode(strConnEnc)
    On Error GoTo Failed
    cnTest.Open strConn
    On Error GoTo 0
    cnTest.Close
    TestConnection = True
    Exit Function
Failed:
    TestConnection = False
End Function
Function sqlCleanString(strUserInput As String) As String
'Clean troublesome characters for SQL or File operations
'Requisites: none
    Dim cleanChar       As String
    Dim singleQuote     As String
    Dim doubleQuote     As String
    Dim semiColon       As String
    Dim singledash      As String
    Dim doubleDash      As String
    Dim commentStart    As String
    Dim commentEnd      As String
    Dim comma           As String
    cleanChar = Chr(32) 'space character which the SQL parser ignores
    singleQuote = Chr(39)
    doubleQuote = Chr(34)
    semiColon = Chr(59)
    singledash = Chr(45)
    doubleDash = Chr(45) & Chr(45)
    commentStart = Chr(47) & Chr(42)
    commentEnd = Chr(42) & Chr(47)
    comma = Chr(44)
    ' replace single quote with double quotes; also properly formats legit possession and contractions
    strUserInput = Replace(strUserInput, singleQuote, doubleQuote)
    ' remove semicolon command delimiter
    strUserInput = Replace(strUserInput, semiColon, comma)
    ' remove double dash comment
    Do While InStr(1, strUserInput, doubleDash) > 0
        strUserInput = Replace(strUserInput, doubleDash, singledash)
    Loop
    ' remove slash begin comment
    strUserInput = Replace(strUserInput, commentStart, singledash)
    ' remove slash end comment
    strUserInput = Replace(strUserInput, commentEnd, singledash)
    'remove xp_ external commands
    strUserInput = Replace(strUserInput, "xp_", cleanChar)
    sqlCleanString = Trim(strUserInput)
End Function
Function Decode(str As String) As String
'Convert a string of ASCII codes into plain text
'Requisites: none
    Dim varArray        As Variant
    Dim x               As Integer
    varArray = Split(str, ";")
    On Error GoTo Decoded:
    For x = LBound(varArray) To UBound(varArray)
        Decode = Decode & Chr(varArray(x))
    Next x
    Exit Function
Decoded:
    Decode = str
End Function
Function Encode(str As String) As String
'Convert a string of plain text into ASCII codes
'Requisites: none
    Dim x       As Integer
    For x = 1 To Len(str)
        Encode = Encode & IIf(x = 1, "", ";") & Asc(Mid(str, x, 1))
    Next x
End Function
Public Function IfNull(val, str)
'Function to replicate Access' Nz or SQL's ISNULL
'Requisites: none
    If IsNull(val) Then
        IfNull = str
    Else
        IfNull = val
    End If
End Function
Public Function NullIf(val, chk)
'Reverse of IfNull, to submit NULLs to database
'Requisites: none
    If val = chk Then
        NullIf = Null
    Else
        NullIf = val
    End If
End Function
Public Function IsEmptyRS(rs As ADODB.Recordset) As Boolean
'Test whether recordset is empty
'Requisites: none
    If rs Is Nothing Then
        IsEmptyRS = True
    ElseIf rs.State = 0 Then
        IsEmptyRS = True
    Else
        IsEmptyRS = False
    End If
End Function
Public Sub rsToRow(rs As ADODB.Recordset, StartRange As Range, Optional HeaderRow As Long = 1)
'Loop through all fields in a recordset, add them to the correct columns (relative to StartRange)
'Requisites: IsEmptyRS
    Dim sht As Worksheet
    Dim cel As Range
    Set sht = StartRange.Parent
    If Not IsEmptyRS(rs) Then
        With sht
            rs.MoveFirst
            Do While Not rs.EOF
                For Each cel In .Range(.Cells(HeaderRow, StartRange.Column), .Cells(HeaderRow, .Columns.Count).End(xlToLeft))
                    On Error Resume Next
                    Debug.Print rs(cel.Value)
                    On Error GoTo 0
                Next cel
                rs.MoveNext
            Loop
        End With
    End If
End Sub
## Appendix: Links
- Code
- Development
- Excel
- Microsoft Office
- Excel - VBA
- SQL
- Stored Procedures - SQL Server Backlinks:
list from [[VBA - SQL Stored Procedure Caller Module]] AND -"Changelog"
#Status/WIP
- 
VBA - Save All¶
## Contents
- Individual Sub Modules
- Whole Save Module
- 
Appendix: Links ## Individual Sub Modules 
- Close Without Save
- 
Save All and Close ### Save All 
- 
SaveAll(Optional CloseSaved As Boolean = False)Sub SaveAll(Optional CloseSaved As Boolean = False) ' This procedure saves all open workbooks ' Created on: 2/28/12 ' by: Scott Conrad Dim Ans As Integer Dim ListAns As Integer Dim i As Integer Dim sUnsavedMessage As String Dim wbActive As Workbook Dim wbBook As Workbook ' For returning to active workbook Set wbActive = ActiveWorkbook ' For populating a list of unsaved files iCtUnsaved = 0 iCtSaved = 0 sUnsavedList = "" i = 0 ' Disabling alerts so that the program will pause Application.DisplayAlerts = False ' Loops through all books For Each wbBook In Application.Workbooks ' Checks if file is not read only and begins to save If wbBook.ReadOnly <> True Then ' If path exists file saves otherwise save prompt is opened If wbBook.Path <> "" Then wbBook.Save iCtSaved = iCtSaved + 1 If CloseSaved = True Then wbBook.Close End If Else Err.Clear wbBook.Activate Ans = 6 Ans = Application.Dialogs(xlDialogSaveAs).Show Do Loop While Ans = 6 If Ans = 0 Then iCtUnsaved = iCtUnsaved + 1 sUnsavedList = sUnsavedList + wbBook.Name + vbCrLf Else If Err <> 0 Then MsgBox wbBook.Name & "did not save. Please try saving later.", vbOK, "Saving" iCtUnsaved = iCtUnsaved + 1 sUnsavedList = sUnsavedList + wbBook.Name + vbCrLf Else iCtSaved = iCtSaved + 1 wbBook.Save If CloseSaved = True Then wbBook.Close End If End If End If Err.Clear End If ' If file is read only, file name is stored for listing in ' unsaved form. Else i = i + 1 iCtUnsaved = iCtUnsaved + 1 sUnsavedList = sUnsavedList + wbBook.Name & vbCrLf End If Next wbBook If CloseSaved = False And iCtUnsaved > 0 Then sUnsavedMessage = "The following files did not save, because they were " sUnsavedMessage = sUnsavedMessage & "either in read-only or new books." ListAns = ListForm(sUnsavedList, sUnsavedMessage, "Save All", typeOK) End If On Error Resume Next wbActive.Activate Application.DisplayAlerts = True End Sub
### Close Without Save
- CloseWithoutSave(Optional bForceClose As Boolean = False)- Sub CloseWithoutSave(Optional bForceClose As Boolean = False) ' Closes excel without saving any of the open files ' Created on: 3/13/12 ' By: S Conrad Dim CloseAns As Integer Dim sClose As String Dim wbBook As Workbook ' Gives the user the option to abort. If bForceClose = False Then sClose = "Would you like to continue closing Excel without saving the open files?" CloseAns = MsgBox(sClose, vbOKCancel, "Close All Files") Else CloseAns = vbOK End If If CloseAns = vbCancel Then Exit Sub ' Tricks excel into thinking workbook was saved and closes workbook leaving the application open For Each wbBook In Workbooks wbBook.Saved = True wbBook.Close (False) Next '' If ok is clicked, all workbooks are closed without the save dialog popup activating. 'If CloseAns = vbOK Then ' Excel.Application.Quit ' End If End Sub
### Save All and Close
- SaveAllAndClose()- Sub SaveAllandClose() Dim sUnsavedMess As String Dim ListAns As Integer Dim wb As Workbook SaveAll (True) If iCtUnsaved > 0 Then sUnsavedMess = "The following files did not save, because they were " sUnsavedMess = sUnsavedMess & "either in read-only or new books. Would " sUnsavedMess = sUnsavedMess & "you like to close these without saving?" ListAns = ListForm(sUnsavedList, sUnsavedMess, "Save and Close", typeYes, typeNo) Else Application.Quit End If Debug.Print "Here are unsaved"; iCtUnsaved If ListAns = vbYes Then For Each wb In Workbooks wb.Saved = True Next wb Excel.Application.Quit End If End Sub
## Whole Save Module
- ModSave.bat- Option Explicit Dim iCtSaved As Integer Dim iCtUnsaved As Integer Dim sUnsavedList As String Sub SaveAll(Optional CloseSaved As Boolean = False) ' This procedure saves all open workbooks ' Created on: 2/28/12 ' by: Scott Conrad Dim Ans As Integer Dim ListAns As Integer Dim i As Integer Dim sUnsavedMessage As String Dim wbActive As Workbook Dim wbBook As Workbook ' For returning to active workbook Set wbActive = ActiveWorkbook ' For populating a list of unsaved files iCtUnsaved = 0 iCtSaved = 0 sUnsavedList = "" i = 0 ' Disabling alerts so that the program will pause Application.DisplayAlerts = False ' Loops through all books For Each wbBook In Application.Workbooks ' Checks if file is not read only and begins to save If wbBook.ReadOnly <> True Then ' If path exists file saves otherwise save prompt is opened If wbBook.Path <> "" Then wbBook.Save iCtSaved = iCtSaved + 1 If CloseSaved = True Then wbBook.Close End If Else Err.Clear wbBook.Activate Ans = 6 Ans = Application.Dialogs(xlDialogSaveAs).Show Do Loop While Ans = 6 If Ans = 0 Then iCtUnsaved = iCtUnsaved + 1 sUnsavedList = sUnsavedList + wbBook.Name + vbCrLf Else If Err <> 0 Then MsgBox wbBook.Name & "did not save. Please try saving later.", vbOK, "Saving" iCtUnsaved = iCtUnsaved + 1 sUnsavedList = sUnsavedList + wbBook.Name + vbCrLf Else iCtSaved = iCtSaved + 1 wbBook.Save If CloseSaved = True Then wbBook.Close End If End If End If Err.Clear End If ' If file is read only, file name is stored for listing in ' unsaved form. Else i = i + 1 iCtUnsaved = iCtUnsaved + 1 sUnsavedList = sUnsavedList + wbBook.Name & vbCrLf End If Next wbBook If CloseSaved = False And iCtUnsaved > 0 Then sUnsavedMessage = "The following files did not save, because they were " sUnsavedMessage = sUnsavedMessage & "either in read-only or new books." ListAns = ListForm(sUnsavedList, sUnsavedMessage, "Save All", typeOK) End If On Error Resume Next wbActive.Activate Application.DisplayAlerts = True End Sub Sub CloseWithoutSave(Optional bForceClose As Boolean = False) ' Closes excel without saving any of the open files ' Created on: 3/13/12 ' By: S Conrad Dim CloseAns As Integer Dim sClose As String Dim wbBook As Workbook ' Gives the user the option to abort. If bForceClose = False Then sClose = "Would you like to continue closing Excel without saving the open files?" CloseAns = MsgBox(sClose, vbOKCancel, "Close All Files") Else CloseAns = vbOK End If If CloseAns = vbCancel Then Exit Sub ' Tricks excel into thinking workbook was saved and closes workbook leaving the application open For Each wbBook In Workbooks wbBook.Saved = True wbBook.Close (False) Next '' If ok is clicked, all workbooks are closed without the save dialog popup activating. 'If CloseAns = vbOK Then ' Excel.Application.Quit ' End If End Sub Sub SaveAllandClose() Dim sUnsavedMess As String Dim ListAns As Integer Dim wb As Workbook SaveAll (True) If iCtUnsaved > 0 Then sUnsavedMess = "The following files did not save, because they were " sUnsavedMess = sUnsavedMess & "either in read-only or new books. Would " sUnsavedMess = sUnsavedMess & "you like to close these without saving?" ListAns = ListForm(sUnsavedList, sUnsavedMess, "Save and Close", typeYes, typeNo) Else Application.Quit End If Debug.Print "Here are unsaved"; iCtUnsaved If ListAns = vbYes Then For Each wb In Workbooks wb.Saved = True Next wb Excel.Application.Quit End If End Sub Private Sub TestSaveAll() SaveAll End Sub
## Appendix: Links
- Code
- Development
- Excel
- Microsoft Office
- Excel - VBA Backlinks:
list from [[VBA - Save All]] AND -"Changelog"
- 
VBA - File Dialog¶
Source: VBA-General/mod_FileDialog.bas at main · ViperSRT3g/VBA-General
Attribute VB_Name = "mod_FileDialog"
Option Explicit
Public Function FileDialog(ByVal DialogType As MsoFileDialogType, _
                           Optional ByVal DialogTitle As String, _
                           Optional ByVal MultiSelect As Boolean, _
                           Optional ByVal Initial As String, _
                           Optional ByRef Filter As Variant) As String()
    'FileDialog returns an array of strings based on user selection
    'Filter Example: "Images, *.gif; *.jpg; *.jpeg"
    Dim Index As Long, SubFilter() As String, Output() As String
    With Application.FileDialog(DialogType)
        If Len(DialogTitle) > 0 Then .Title = DialogTitle
        If Len(Initial) > 0 Then .InitialFileName = Initial & "\"
        .AllowMultiSelect = MultiSelect
        If DialogType = msoFileDialogFilePicker Or DialogType = msoFileDialogOpen Then
            If Not IsMissing(Filter) Then
                .Filters.Clear
                If (VarType(Filter) And vbArray) = vbArray Then 'An array was passed
                    For Index = LBound(Filter) To UBound(Filter)
                        If InStr(Filter(Index), ",") Then 'Verify supplied filter is parse-able
                            SubFilter = Split(Filter(Index), ",")
                            .Filters.Add Trim(SubFilter(0)), Trim(SubFilter(1)) 'If you didn't supply the Filters properly, then this is your fault
                        End If
                    Next Index
                ElseIf (VarType(Filter) And vbString) = vbString Then 'A single string was passed
                    If InStr(Filter, ",") Then
                        SubFilter = Split(Filter, ",")
                        .Filters.Add Trim(SubFilter(0)), Trim(SubFilter(1)) 'If you didn't supply the Filters properly, then this is your fault
                    End If
                End If
            End If
        End If
        .Show
        'Process file selection (Whether there was a file selected or not)
        Select Case .SelectedItems.Count
            Case 0: ReDim Output(0) As String
            Case Else: ReDim Output(.SelectedItems.Count - 1) As String
        End Select
        For Index = 0 To .SelectedItems.Count - 1
            Output(Index) = .SelectedItems(Index + 1)
        Next Index
        FileDialog = Output
    End With
End Function
## Appendix: Links
- Code
- Development
- Excel
- Microsoft Office
- Excel - VBA Backlinks:
list from [[VBA - File Dialog]] AND -"Changelog"
- 
VBA - Page Setup and Print Macros¶
## Contents
- Individual Sub Modules
- Entire Print and Page Module
- Appendix: Links ## Individual Sub Modules
The following Sub’s are included:
- Setup and Optimization
- Set Print DPI
- Set Print to Black and White
- Unhide All Sheets
- 
All Read Only ### Setup and Optimization 
- 
Setup & InitGlobalFastApp()Option Explicit ' These are used to speed up vba code Public DefCalcState As Integer Public DefEventState As Integer Public DefScrUpdState As Integer Sub InitGlobalFastApp() ' Used to speed up vba code. ' Created on: 3/26/12 ' By: S Conrad ' Stores default settings and changes them to speed up code With Application DefCalcState = .Calculation DefEventState = .EnableEvents DefScrUpdState = .ScreenUpdating .Calculation = xlCalculationManual .EnableEvents = False .ScreenUpdating = False End With End Sub
### Set Print DPI
- SetPrintDPI()- Sub SetPrintDPI() ' Allows the user to select from a list of available print qualities and changes ' all pages in the current workbook. ' Created on: 3/14/12 ' By: S Conrad Dim bExitLoop As Boolean Dim oldStatusBar As Boolean Dim i As Double Dim sDefDPI As Double Dim dDPI As Double Dim vDPI As Variant Dim wsWkSheet As Worksheet Dim wsAW As Worksheet Dim Ans As Double Dim sAnsMsg As String Dim SampleDPI As String Dim sFormQuest As String ' Cancels procedure if no workbooks are open If Workbooks.Count = 0 Then MsgBox "No workbooks are open.", , "Change Print Resolution" Exit Sub End If ' Stores initial settings 'InitGlobalFastApp Set wsAW = ActiveSheet sDefDPI = CStr(wsAW.PageSetup.PrintQuality(1)) oldStatusBar = Application.DisplayStatusBar ' Sets print quality to 600 if available On Error Resume Next ActiveSheet.PageSetup.PrintQuality = 600 If Err = 0 Then Application.DisplayStatusBar = True For Each wsWkSheet In Sheets Application.StatusBar = wsWkSheet.Name & "'s print quality is being changed to 600 DPi." wsWkSheet.PageSetup.PrintQuality = 600 wsWkSheet.DisplayPageBreaks = False Next wsAW.Activate Application.StatusBar = False Application.DisplayStatusBar = oldStatusBar Exit Sub Else sAnsMsg = "This printer does not have a print setting of 600 DPi." & vbCrLf & _ "Would you like to see a list of available resolutions?" Ans = MsgBox(sAnsMsg, vbOKCancel, "Setting Print Resolution") If Ans = vbCancel Then Exit Sub End If Application.DisplayStatusBar = True Application.StatusBar = "Please wait. A list of available print qualities is being populated" ' Populate a list of possible print qualities SampleDPI = "" For i = 100 To 1200 Step 50 On Error Resume Next ActiveSheet.PageSetup.PrintQuality = i If Err = 0 Then SampleDPI = SampleDPI & i & vbCrLf Next ActiveSheet.DisplayPageBreaks = False ' Returns status bar to original state Application.StatusBar = False Application.DisplayStatusBar = oldStatusBar ' Construction of messages to send to the user SampleDPI = Left(SampleDPI, Len(SampleDPI) - 2) sFormQuest = "Please choose a print quality. The drop down list " sFormQuest = sFormQuest & "contains some available print qualities. " sFormQuest = sFormQuest & "Other print qualities are allowed. Refer " sFormQuest = sFormQuest & "to the page setup form of the page layout tab " sFormQuest = sFormQuest & "for other available qualities." ' This loop shows the combo form and waits for the user to enter an acceptable answer bExitLoop = False Do vDPI = ComboForm(SampleDPI, sFormQuest, "Print Quality", sDefDPI, _ "DPI") ' Exits if the user cancels If vDPI = vbCancel Or cmbCancel = vbCancel Then ' With Application ' .Calculation = DefCalcState ' .ScreenUpdating = DefScrUpdState ' .EnableEvents = DefEventState ' End With wsAW.Activate wsAW.PageSetup.PrintQuality = sDefDPI wsAW.DisplayPageBreaks = False Unload FmComboBox Exit Sub End If ' Only allows integers If WorksheetFunction.IsNumber(vDPI) Or vDPI > 1 Then dDPI = CDbl(vDPI) Else MsgBox "Please enter a value greater than one.", vbOKOnly, "Print Settings" dDPI = 0 End If ' Checks if the DPI is available On Error Resume Next ActiveSheet.PageSetup.PrintQuality = dDPI If Err <> 0 Then dDPI = 0 MsgBox "The selected pring quality is not availabe for this printer.", vbOKOnly, _ "Print Quality" Else bExitLoop = True End If Unload FmComboBox Loop Until bExitLoop = True ' Change each pages print quality and hide page breaks Application.DisplayStatusBar = True For Each wsWkSheet In Sheets Application.StatusBar = wsWkSheet.Name & "'s print quality is being changed to " & dDPI & " DPi." wsWkSheet.PageSetup.PrintQuality = dDPI wsWkSheet.DisplayPageBreaks = False Next ' Returns status bar to original state Application.StatusBar = False Application.DisplayStatusBar = oldStatusBar ' Return application to original state wsAW.Activate 'With Application ' .Calculation = DefCalcState ' .ScreenUpdating = DefScrUpdState ' .EnableEvents = DefEventState ' End With End Sub
### Set Print to Black and White
- SetPrintBlackandWhite()- Sub SetPrintBlackandWhite() ' Changes print ' Revised on: 2/18/12 ' by: Scott Conrad Dim oldStatusBar As Boolean Dim wsSheet As Worksheet ' Cancels procedure if no workbooks are open If Workbooks.Count = 0 Then MsgBox "No workbooks are open.", , "Change Print Resolution" Exit Sub End If ' Stores initial settings oldStatusBar = Application.DisplayStatusBar Application.DisplayStatusBar = True 'InitGlobalFastApp ' Change print to black and white and hide page breaks For Each wsSheet In Sheets Application.StatusBar = wsSheet.Name & " is being set to Black and White" wsSheet.PageSetup.BlackAndWhite = True wsSheet.DisplayPageBreaks = False Next wsSheet Application.StatusBar = False Application.DisplayStatusBar = oldStatusBar ' Returns to original state 'With Application ' .Calculation = DefCalcState ' .ScreenUpdating = DefScrUpdState ' .EnableEvents = DefEventState ' End With End Sub
### Unhide All Sheets
- UnhideAllSheets()- Sub UnhideAllSheets() ' Unhides all sheets. This works with or without index tab. ' Revised on: 2/18/12 ' by: Scott Conrad ' Cancels procedure if no workbooks are open If Workbooks.Count = 0 Then MsgBox "No workbooks are open.", , "Change Print Resolution" Exit Sub End If Dim wsSheet As Worksheet ' Change sheets visibility For Each wsSheet In Worksheets wsSheet.Visible = xlSheetVisible Next End Sub
### All Read Only
- AllReadOnly()- Sub AllReadOnly() ' Changes every file to read only without the save dialog ' Created on: 3/13/12 ' By: S Conrad Dim i As Integer Dim aw As Workbook ' Exits if workbooks are not open If Workbooks.Count < 1 Then Exit Sub ' Changes each open workbook to read only and deactivates the save application popup. Set aw = ActiveWorkbook For i = 1 To Workbooks.Count On Error Resume Next Workbooks(i).Saved = True ' Tricks excel into thinking file is saved Workbooks(i).ChangeFileAccess xlReadOnly Next i ' Returns Excel to original state aw.Activate End Sub
## Entire Print and Page Module
- ModPrintAndPage.bas- Option Explicit ' These are used to speed up vba code Public DefCalcState As Integer Public DefEventState As Integer Public DefScrUpdState As Integer Sub SetPrintDPI() ' Allows the user to select from a list of available print qualities and changes ' all pages in the current workbook. ' Created on: 3/14/12 ' By: S Conrad Dim bExitLoop As Boolean Dim oldStatusBar As Boolean Dim i As Double Dim sDefDPI As Double Dim dDPI As Double Dim vDPI As Variant Dim wsWkSheet As Worksheet Dim wsAW As Worksheet Dim Ans As Double Dim sAnsMsg As String Dim SampleDPI As String Dim sFormQuest As String ' Cancels procedure if no workbooks are open If Workbooks.Count = 0 Then MsgBox "No workbooks are open.", , "Change Print Resolution" Exit Sub End If ' Stores initial settings 'InitGlobalFastApp Set wsAW = ActiveSheet sDefDPI = CStr(wsAW.PageSetup.PrintQuality(1)) oldStatusBar = Application.DisplayStatusBar ' Sets print quality to 600 if available On Error Resume Next ActiveSheet.PageSetup.PrintQuality = 600 If Err = 0 Then Application.DisplayStatusBar = True For Each wsWkSheet In Sheets Application.StatusBar = wsWkSheet.Name & "'s print quality is being changed to 600 DPi." wsWkSheet.PageSetup.PrintQuality = 600 wsWkSheet.DisplayPageBreaks = False Next wsAW.Activate Application.StatusBar = False Application.DisplayStatusBar = oldStatusBar Exit Sub Else sAnsMsg = "This printer does not have a print setting of 600 DPi." & vbCrLf & _ "Would you like to see a list of available resolutions?" Ans = MsgBox(sAnsMsg, vbOKCancel, "Setting Print Resolution") If Ans = vbCancel Then Exit Sub End If Application.DisplayStatusBar = True Application.StatusBar = "Please wait. A list of available print qualities is being populated" ' Populate a list of possible print qualities SampleDPI = "" For i = 100 To 1200 Step 50 On Error Resume Next ActiveSheet.PageSetup.PrintQuality = i If Err = 0 Then SampleDPI = SampleDPI & i & vbCrLf Next ActiveSheet.DisplayPageBreaks = False ' Returns status bar to original state Application.StatusBar = False Application.DisplayStatusBar = oldStatusBar ' Construction of messages to send to the user SampleDPI = Left(SampleDPI, Len(SampleDPI) - 2) sFormQuest = "Please choose a print quality. The drop down list " sFormQuest = sFormQuest & "contains some available print qualities. " sFormQuest = sFormQuest & "Other print qualities are allowed. Refer " sFormQuest = sFormQuest & "to the page setup form of the page layout tab " sFormQuest = sFormQuest & "for other available qualities." ' This loop shows the combo form and waits for the user to enter an acceptable answer bExitLoop = False Do vDPI = ComboForm(SampleDPI, sFormQuest, "Print Quality", sDefDPI, _ "DPI") ' Exits if the user cancels If vDPI = vbCancel Or cmbCancel = vbCancel Then ' With Application ' .Calculation = DefCalcState ' .ScreenUpdating = DefScrUpdState ' .EnableEvents = DefEventState ' End With wsAW.Activate wsAW.PageSetup.PrintQuality = sDefDPI wsAW.DisplayPageBreaks = False Unload FmComboBox Exit Sub End If ' Only allows integers If WorksheetFunction.IsNumber(vDPI) Or vDPI > 1 Then dDPI = CDbl(vDPI) Else MsgBox "Please enter a value greater than one.", vbOKOnly, "Print Settings" dDPI = 0 End If ' Checks if the DPI is available On Error Resume Next ActiveSheet.PageSetup.PrintQuality = dDPI If Err <> 0 Then dDPI = 0 MsgBox "The selected pring quality is not availabe for this printer.", vbOKOnly, _ "Print Quality" Else bExitLoop = True End If Unload FmComboBox Loop Until bExitLoop = True ' Change each pages print quality and hide page breaks Application.DisplayStatusBar = True For Each wsWkSheet In Sheets Application.StatusBar = wsWkSheet.Name & "'s print quality is being changed to " & dDPI & " DPi." wsWkSheet.PageSetup.PrintQuality = dDPI wsWkSheet.DisplayPageBreaks = False Next ' Returns status bar to original state Application.StatusBar = False Application.DisplayStatusBar = oldStatusBar ' Return application to original state wsAW.Activate 'With Application ' .Calculation = DefCalcState ' .ScreenUpdating = DefScrUpdState ' .EnableEvents = DefEventState ' End With End Sub Sub SetPrintBlackandWhite() ' Changes print ' Revised on: 2/18/12 ' by: Scott Conrad Dim oldStatusBar As Boolean Dim wsSheet As Worksheet ' Cancels procedure if no workbooks are open If Workbooks.Count = 0 Then MsgBox "No workbooks are open.", , "Change Print Resolution" Exit Sub End If ' Stores initial settings oldStatusBar = Application.DisplayStatusBar Application.DisplayStatusBar = True 'InitGlobalFastApp ' Change print to black and white and hide page breaks For Each wsSheet In Sheets Application.StatusBar = wsSheet.Name & " is being set to Black and White" wsSheet.PageSetup.BlackAndWhite = True wsSheet.DisplayPageBreaks = False Next wsSheet Application.StatusBar = False Application.DisplayStatusBar = oldStatusBar ' Returns to original state 'With Application ' .Calculation = DefCalcState ' .ScreenUpdating = DefScrUpdState ' .EnableEvents = DefEventState ' End With End Sub Sub UnhideAllSheets() ' Unhides all sheets. This works with or without index tab. ' Revised on: 2/18/12 ' by: Scott Conrad ' Cancels procedure if no workbooks are open If Workbooks.Count = 0 Then MsgBox "No workbooks are open.", , "Change Print Resolution" Exit Sub End If Dim wsSheet As Worksheet ' Change sheets visibility For Each wsSheet In Worksheets wsSheet.Visible = xlSheetVisible Next End Sub Sub AllReadOnly() ' Changes every file to read only without the save dialog ' Created on: 3/13/12 ' By: S Conrad Dim i As Integer Dim aw As Workbook ' Exits if workbooks are not open If Workbooks.Count < 1 Then Exit Sub ' Changes each open workbook to read only and deactivates the save application popup. Set aw = ActiveWorkbook For i = 1 To Workbooks.Count On Error Resume Next Workbooks(i).Saved = True ' Tricks excel into thinking file is saved Workbooks(i).ChangeFileAccess xlReadOnly Next i ' Returns Excel to original state aw.Activate End Sub Sub InitGlobalFastApp() ' Used to speed up vba code. ' Created on: 3/26/12 ' By: S Conrad ' Stores default settings and changes them to speed up code With Application DefCalcState = .Calculation DefEventState = .EnableEvents DefScrUpdState = .ScreenUpdating .Calculation = xlCalculationManual .EnableEvents = False .ScreenUpdating = False End With End Sub
## Appendix: Links
- Code
- Development
- Excel
- Microsoft Office
- Excel - VBA Backlinks:
list from [[VBA - Page Setup and Print Macros]] AND -"Changelog"
- 
VBA - Module Template¶
*Source: *
## Appendix: Links
- Code
- Development
- Excel
- Microsoft Office
- Excel - VBA Backlinks:
list from [[VBA - Module Template]] AND -"Changelog"
- 
VBA - Make All Open Files Read Only¶
*Source: *
Sub AllReadOnly()
' Changes every file to read only without the save dialog
' 2014-01-18
' By: Jimmy Briggs
Dim i As Integer
Dim aw As Workbook
' Exits if workbooks are not open
If Workbooks.Count < 1 Then Exit Sub
' Changes each open workbook to read only and deactivates the save application popup.
Set aw = ActiveWorkbook
For i = 1 To Workbooks.Count
    On Error Resume Next
    Workbooks(i).Saved = True ' Tricks excel into thinking file is saved
    Workbooks(i).ChangeFileAccess xlReadOnly
    Next i
' Returns Excel to original state
aw.Activate
End Sub
## Appendix: Links
- Code
- Development
- Excel
- Microsoft Office
- Excel - VBA Backlinks:
list from [[VBA - Make All Open Files Read Only]] AND -"Changelog"
- 
VBA - ListLinks Module¶
*Source: *
Sub ListLinks()
    Dim xSheet As Worksheet
    Dim xRg As Range
    Dim xCell As Range
    Dim xCount As Long
    Dim xLinkArr() As String
    On Error Resume Next
    For Each xSheet In Worksheets
        Set xRg = xSheet.UsedRange.SpecialCells(xlCellTypeFormulas)
        If xRg Is Nothing Then GoTo LblNext
        For Each xCell In xRg
            If InStr(1, xCell.Formula, "[") > 0 Then
                xCount = xCount + 1
                ReDim Preserve xLinkArr(1 To 2, 1 To xCount)
                xLinkArr(1, xCount) = xCell.Address(, , , True)
                xLinkArr(2, xCount) = "'" & xCell.Formula
           End If
        Next
LblNext:
    Next
    If xCount > 0 Then
        Sheets.Add(Sheets(1)).Name = "Link Sheet"
        Range("A1").Resize(, 2).Value = Array("Location", "Reference")
        Range("A2").Resize(UBound(xLinkArr, 2), UBound(xLinkArr, 1)).Value = Application.Transpose(xLinkArr)
        Columns("A:B").AutoFit
    Else
        MsgBox "No links were found within the active workbook.", vbInformation, "KuTools for Excel"
    End If
End Sub
## Appendix: Links
- Code
- Development
- Excel
- Microsoft Office
- Excel - VBA Backlinks:
list from [[VBA - ListLinks Module]] AND -"Changelog"
- 
VBA - Balloon Notification¶
*Source: *
Attribute VB_Name = "mod_BalloonNotification"
Option Explicit
Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long
Declare Function Shell_NotifyIcon Lib "shell32.dll" Alias "Shell_NotifyIconA" ( _
    ByVal dwMessage As Long, _
    lpData As NOTIFYICONDATA) As Long
Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" ( _
    ByVal lpPrevWndFunc As Long, _
    ByVal hwnd As Long, _
    ByVal Msg As Long, _
    ByVal wParam As Long, _
    ByVal lParam As Long) As Long
Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" ( _
    ByVal hwnd As Long, _
    ByVal nIndex As Long, _
    ByVal dwNewLong As Long) As Long
Declare Function FindWindow Lib "user32" Alias "FindWindowA" ( _
    ByVal lpClassName As String, _
    ByVal lpWindowName As String) As Long
Declare Function ExtractIcon Lib "shell32.dll" Alias "ExtractIconA" ( _
    ByVal hInst As Long, _
    ByVal lpszExeFileName As String, _
    ByVal nIconIndex As Long) As Long
Public Const WM_LBUTTONDOWN = &H201
Public Const WM_LBUTTONUP = &H202
Public Const WM_LBUTTONDBL = &H203
Public Const WM_RBUTTONDOWN = &H204
Public Const WM_RBUTTONUP = &H205
Public Const WM_RBUTTONDBL = &H206
Public Const WM_ACTIVATEAPP = &H1C
Public Const NIS_HIDDEN = &H1
Public Const NIS_SHAREDICON = &H2
Public Const NIF_ICON = &H2
Public Const NIF_MESSAGE = &H1
Public Const NIF_TIP = &H4
Public Const NIF_STATE = &H8
Public Const NIF_INFO = &H10
Public Const NIM_ADD = &H0
Public Const NIM_MODIFY = &H1
Public Const NIM_DELETE = &H2
Public Const WM_MOUSEMOVE = &H200
Public Const MAX_TOOLTIP As Integer = 128
Public Const GWL_WNDPROC = (-4)
'shell version / NOTIFIYICONDATA struct size constants
Public Const NOTIFYICONDATA_V1_SIZE As Long = 88  'pre-5.0 structure size
Public Const NOTIFYICONDATA_V2_SIZE As Long = 488 'pre-6.0 structure size
Public Const NOTIFYICONDATA_V3_SIZE As Long = 504 '6.0+ structure size
Public NOTIFYICONDATA_SIZE As Long
Type NOTIFYICONDATA
    cbSize As Long
    hwnd As Long
    uID As Long
    uFlags As Long
    uCallbackMessage As Long
    hIcon As Long
    szTip As String * MAX_TOOLTIP
    dwState As Long
    dwStateMask As Long
    szInfo As String * 256
    uTimeout As Long
    szInfoTitle As String * 64
    dwInfoFlags As Long
End Type
Public nfIconData As NOTIFYICONDATA
' list the icon types for the balloon message..
Public Const vbNone = 0
Public Const vbInformation = 1
Public Const vbExclamation = 2
Public Const vbCritical = 3
Private FHandle As Long
Private WndProc As Long
Private Hooking As Boolean
Private Sub Hook(Lwnd As Long)
    If Hooking = False Then
        FHandle = Lwnd
        WndProc = SetWindowLong(Lwnd, GWL_WNDPROC, AddressOf WindowProc)
        Hooking = True
    End If
End Sub
Private Sub Unhook()
    If Hooking = True Then
        SetWindowLong FHandle, GWL_WNDPROC, WndProc
        Hooking = False
    End If
End Sub
Private Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    If Hooking Then
        If lParam = WM_LBUTTONDBL Then
            UserForm1.Show 1
            WindowProc = True
            '   Unhook
            Exit Function
        End If
        WindowProc = CallWindowProc(WndProc, hw, uMsg, wParam, lParam)
    End If
End Function
Private Sub RemoveIconFromTray()
    Shell_NotifyIcon NIM_DELETE, nfIconData
End Sub
Private Sub AddIconToTray(MeHwnd As Long, MeIcon As Long, MeIconHandle As Long, Tip As String)
    With nfIconData
        .hwnd = MeHwnd
        .uID = MeIcon
        .uFlags = NIF_MESSAGE Or NIF_ICON Or NIF_TIP
        .uCallbackMessage = WM_RBUTTONUP
        .dwState = NIS_SHAREDICON
        .hIcon = MeIconHandle
        .szTip = Tip & Chr$(0)
        .cbSize = NOTIFYICONDATA_V3_SIZE
    End With
    Shell_NotifyIcon NIM_ADD, nfIconData
End Sub
Private Sub BalloonPopUp(ByVal Title As String, ByVal Message As String)
    ' ok, create a balloon popup..
    With nfIconData
        .dwInfoFlags = vbInformation
        .uFlags = NIF_INFO
        .szInfoTitle = Title & vbNullChar
        .szInfo = Message & vbNullChar
    End With
    ' ok, write it to the system tray icon
    Shell_NotifyIcon NIM_MODIFY, nfIconData
End Sub
Private Function FindWindowd(ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    FindWindowd = FindWindow(lpClassName, lpWindowName)
End Function
Private Function ExtractIcond(ByVal hInst As Long, ByVal lpszExeFileName As String, ByVal nIconIndex As Long) As Long
    ExtractIcond = ExtractIcon(hInst, lpszExeFileName, nIconIndex)
End Function
Public Sub DisplayNotification(ByVal Title As String, ByVal Message As String)
    Dim Me_hWnd As Long
    Dim Me_Icon As Long
    Dim Me_Icon_Handle As Long
    Dim IconPath As String
    Me_hWnd = FindWindowd("XLMAIN", ThisWorkbook.Name & " - Excel")
    IconPath = Application.Path & Application.PathSeparator & "excel.exe"
    Me_Icon_Handle = ExtractIcond(0, IconPath, 0)
    Call Hook(Me_hWnd)
    Call AddIconToTray(Me_hWnd, 0, Me_Icon_Handle, "Double Click to re-open userform")
    Call BalloonPopUp(Title, Message)
End Sub
Public Sub RemoveNotificationHooks()
    Call RemoveIconFromTray
    Call Unhook
End Sub
## Appendix: Links
- Code
- Development
- Excel
- Microsoft Office
- Excel - VBA Backlinks:
list from [[VBA - Balloon Notification]] AND -"Changelog"
- 
VBA - Copy Module from one Workbook to Another¶
Source: VBA-General/mod_VBA.bas at main · ViperSRT3g/VBA-General
Option Explicit
Public Sub CopyModule(ByRef SourceWB As Workbook, ByVal strModuleName As String, ByRef TargetWB As Workbook)
    ' Description:  copies a module from one workbook to another
    ' example: CopyModule Workbooks(ThisWorkbook), "Module2",
    '          Workbooks("Food Specials Rolling Depot Memo 46 - 01.xlsm")
    ' Notes:   If Module to be copied already exists, it is removed first,
    '          and afterwards copied
    Dim strFolder As String, strTempFile As String, FName As String
    If Trim(strModuleName) = vbNullString Then Exit Sub
    If TargetWB Is Nothing Then
        MsgBox "Error: Target Workbook " & TargetWB.Name & " doesn't exist (or closed)", vbCritical
        Exit Sub
    End If
    strFolder = SourceWB.Path
    If Len(strFolder) = 0 Then strFolder = CurDir
    ' create temp file and copy "Module2" into it
    strFolder = strFolder & "\"
    strTempFile = strFolder & "~tmpexport.bas"
    On Error Resume Next
    FName = Environ("Temp") & "\" & strModuleName & ".bas"
    If Dir(FName, vbNormal + vbHidden + vbSystem) <> vbNullString Then
        Err.Clear
        Kill FName
        If Err.Number <> 0 Then
            MsgBox "Error copying module " & strModuleName & "  from Workbook " & SourceWB.Name & " to Workbook " & TargetWB.Name, vbInformation
            Exit Sub
        End If
    End If
    ' remove "Module2" if already exits in destination workbook
    With TargetWB.VBProject.VBComponents.Remove.Item(strModuleName)
    ' copy "Module2" from temp file to destination workbook
    SourceWB.VBProject.VBComponents(strModuleName).Export strTempFile
    TargetWB.VBProject.VBComponents.Import strTempFile
    Kill strTempFile
    On Error GoTo 0
End Sub
## Appendix: Links
- Code
- Development
- Excel
- Microsoft Office
- Excel - VBA Backlinks:
list from [[VBA - Copy Module from one Workbook to Another]] AND -"Changelog"
- 
VBA - Create and Run a SQL Query¶
*Source: *
Sub CreateAndRunQuery()
    '------------------------------------------------------------------------------------------
    'This macro opens the Sample.accdb database, creates and runs an SQL query (filtering
    'all the customers from Canada). Then, it copies selected fields back in the Excel sheet.
    'The code uses late binding, so no reference to external library is required.
    'Written By:    Christos Samaras
    'Date:          05/10/2013
    'Last Updated:  29/11/2014
    'E-mail:        xristos.samaras@gmail.com
    'Site:          http://www.myengineeringworld.net
    '------------------------------------------------------------------------------------------
    'Declaring the necessary variables.
    Dim con         As Object
    Dim rs          As Object
    Dim AccessFile  As String
    Dim strTable    As String
    Dim SQL         As String
    Dim i           As Integer
    'Disable screen flickering.
    Application.ScreenUpdating = False
    'Specify the file path of the accdb file. You can also use the full path of the file like:
    'AccessFile = "C:\Users\Christos\Desktop\Sample.accdb"
    AccessFile = ThisWorkbook.Path & "\" & "Sample.accdb"
    'Set the name of the table you want to retrieve the data.
    strTable = "Customers"
    On Error Resume Next
    'Create the ADODB connection object.
    Set con = CreateObject("ADODB.connection")
    'Check if the object was created.
    If Err.Number <> 0 Then
        MsgBox "Connection was not created!", vbCritical, "Connection Error"
        Exit Sub
    End If
    On Error GoTo 0
    'Open the connection.
    con.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & AccessFile
    'Create the SQL statement to retrieve the data from table.
    'Get the necessary information (first name etc.) for all the Canadian customers.
    SQL = "SELECT FirstName, LastName, Address, City, Phone FROM " & strTable & " WHERE COUNTRY='Canada'"
    On Error Resume Next
    'Create the ADODB recordset object.
    Set rs = CreateObject("ADODB.Recordset")
    'Check if the object was created.
    If Err.Number <> 0 Then
        'Error! Release the objects and exit.
        Set rs = Nothing
        Set con = Nothing
        'Display an error message to the user.
        MsgBox "Recordset was not created!", vbCritical, "Recordset Error"
        Exit Sub
    End If
    On Error GoTo 0
    'Set thee cursor location.
    rs.CursorLocation = 3 'adUseClient on early  binding
    rs.CursorType = 1 'adOpenKeyset on early  binding
    'Open the recordset.
    rs.Open SQL, con
    'Check if the recordet is empty.
    If rs.EOF And rs.BOF Then
        'Close the recordet and the connection.
        rs.Close
        con.Close
        'Release the objects.
        Set rs = Nothing
        Set con = Nothing
        'Enable the screen.
        Application.ScreenUpdating = True
        'In case of an empty recordset display an error.
        MsgBox "There are no records in the recordset!", vbCritical, "No Records"
        Exit Sub
    End If
    'Copy the recordset headers.
    For i = 0 To rs.Fields.Count - 1
        Sheets("New Query").Cells(1, i + 1) = rs.Fields(i).Name
    Next i
    'Write the query values in the sheet.
    Sheets("New Query").Range("A2").CopyFromRecordset rs
    'Close the recordet and the connection.
    rs.Close
    con.Close
    'Release the objects.
    Set rs = Nothing
    Set con = Nothing
    'Adjust the columns' width.
    Sheets("New Query").Columns("A:E").AutoFit
    'Enable the screen.
    Application.ScreenUpdating = True
    'Inform the user that the macro was executed successfully.
    MsgBox "The Canadian customers were successfully retrieved from the '" & strTable & "' table!", vbInformation, "Done"
End Sub
## Appendix: Links
- Code
- Development
- Excel
- Microsoft Office
- Excel - VBA Backlinks:
list from [[VBA - Create and Run a SQL Query]] AND -"Changelog"
- 
VBA - Check for Broken Links in Workbook¶
Source: Excel: How to find broken links and get them fixed - Ablebits.com
Sub FindBrokenLinks()
    linksDataArray = ActiveWorkbook.LinkSources(xlExcelLinks)
    Dim reportHeaders() As String
    Dim rangeCur As Range
    Dim sheetCur As Worksheet
    Dim rowNo As Integer
    Dim linkFilePath, linkFilePath2, linkFileName As String
    Dim linksStatusDescr As String  'https://docs.microsoft.com/en-us/office/vba/api/excel.xllinkstatus
    Dim sheetReportName As String
    sheetReportName = "Broken Links report"
    linksStatusDescr = "File missing"
    reportHeaders = Split("Worksheet, Cell, Formula, Workbook, Link Status", ", ")
    rowNo = 1 'Header row
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    If Evaluate("ISREF('" & sheetReportName & "'!A1)") Then
        ActiveWorkbook.Worksheets(sheetReportName).Cells.Clear
    Else
        Sheets.Add.Name = sheetReportName
    End If
    Set sheetReport = ActiveWorkbook.Worksheets(sheetReportName)
    For indI = 0 To UBound(reportHeaders)
        sheetReport.Cells(rowNo, indI + 1) = reportHeaders(indI)
    Next
    For Each sheetCur In ActiveWorkbook.Worksheets
        If sheetCur.Name <> sheetReport.Name Then
            For Each rangeCur In sheetCur.UsedRange
                If rangeCur.HasFormula Then
                    For indI = LBound(linksDataArray) To UBound(linksDataArray)
                        linkFilePath = linksDataArray(indI)   'LinkSrouces returns the full file path with the file name
                        linkFileName = Right(linkFilePath, Len(linkFilePath) - InStrRev(linkFilePath, "\"))   'extract only the file name
                        linkFilePath2 = Left(linksDataArray(indI), InStrRev(linksDataArray(indI), "\")) & "[" & linkFileName & "]"  'the file path with the workbook name in square brackets
                        linksStatusCode = ActiveWorkbook.LinkInfo( CStr(linkFilePath), xlLinkInfoStatus)
                        If xlLinkStatusMissingFile = linksStatusCode And (InStr(rangeCur.Formula, linkFilePath) Or InStr(rangeCur.Formula, linkFilePath2)) Then
                            rowNo = rowNo + 1
                            With sheetReport
                                .Cells(rowNo, 1) = sheetCur.Name
                                .Cells(rowNo, 2) = Replace(rangeCur.Address, "$", "")
                                .Hyperlinks.Add Anchor:=.Cells(rowNo, 2), Address:="", SubAddress:="'" & sheetCur.Name & "'!" & rangeCur.Address
                                .Cells(rowNo, 3) = "'" & rangeCur.Formula
                                .Cells(rowNo, 4) = linkFilePath
                                .Cells(rowNo, 5) = linksStatusDescr
                            End With
                            Exit For
                        End If
                    Next indI
                    For Each namedrangeCur In Names
                       If InStr(rangeCur.Formula, namedrangeCur.Name) Then
                            linkFilePath = ""
                            linksStatusCode = -1
                            If 0 < InStr(namedrangeCur.RefersTo, "[") Then
                                linkFilePath = Replace( Split( Right(namedrangeCur.RefersTo, Len(namedrangeCur.RefersTo) - 2), "]")(0), "[", "")
                                linksStatusCode = ActiveWorkbook.LinkInfo( CStr(linkFilePath), xlLinkInfoStatus)
                            End If
                            If xlLinkStatusMissingFile = linksStatusCode Then
                                rowNo = rowNo + 1
                               With sheetReport
                                   .Cells(rowNo, 1) = sheetCur.Name
                                   .Cells(rowNo, 2) = Replace(rangeCur.Address, "$", "")
                                   .Hyperlinks.Add Anchor:=.Cells(rowNo, 2), Address:="", SubAddress:="'" & sheetCur.Name & "'!" & rangeCur.Address
                                   .Cells(rowNo, 3) = "'" & rangeCur.Formula
                                   .Cells(rowNo, 4) = linkFilePath
                                   If 0 < Len(linkFilePath) Then
                                    .Cells(rowNo, 5) = linksStatusDescr
                                   End If
                               End With
                            End If
                            Exit For
                        End If
                    Next namedrangeCur
                End If
            Next rangeCur
        End If
    Next
    Columns("A:E").EntireColumn.AutoFit
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic
End Sub
A list of invalid links is output in a new worksheet named Broken Links report. Column B has a hyperlink to the cell containing the link.

You can insert the code in your own workbook or download our sample file with the macro as well as the step-by-step instructions on how to use it.
Note. This code only finds links to invalid workbooks (non-existent, moved or deleted), but not missing sheets. The reason is that the LinkInfo method checks just the file name. An attempt to check a sheet name results in Error 2015.
## Appendix: Links
- Code
- Development
- Excel
- Microsoft Office
- Excel - VBA Backlinks:
list from [[VBA - Check for Broken Links in Workbook]] AND -"Changelog"
- 
VBA - Alert¶
*Source: *
Option Explicit
Private Declare Function sndPlaySound32 Lib "winmm.dll" Alias "sndPlaySoundA" (ByVal lpszSoundName As String, ByVal uFlags As Long) As Long
Public Function Alert(ByVal Prompt As String, Optional Buttons As VbMsgBoxStyle, Optional ByVal Title As String, Optional SoundPath As String, Optional SoundFlag As Long = 1) As VbMsgBoxResult
    Call Sound(SoundPath, SoundFlag)
    Alert = MsgBox(Prompt, Buttons, Title)
End Function
Public Function Sound(ByVal FilePath As String, Optional ByVal Flag As Long = 1) As Boolean
    If Len(FilePath) > 0 Then
        Dim FSO As Object: Set FSO = CreateObject("Scripting.FileSystemObject")
        If FSO.FileExists(FilePath) Then Sound = sndPlaySound32(FilePath, Flag)
        Set FSO = Nothing
    End If
End Function
## Appendix: Links
- Code
- Development
- Excel
- Microsoft Office
- Excel - VBA Backlinks:
list from [[VBA - Alert]] AND -"Changelog"
Appendix: Links¶
DataView
list from "2-Areas/Code/Windows/Visual Basic" AND !#Type/Readme
Backlinks
list from [[_README]] AND -"Changelog"