# Excel Macro



## msmb (Dec 25, 2022)

Want one macro code wherein I need to copy the data as it is reflecting in the source file (BS Tab only) however if I run the macro the format changes. Rest all the tabs are working properly. Please someone help me out. Below mention are the coding which I used in my macro


```
Sub ChangeFormat()
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
   
    Dim Rng As Range
   
    Dim folderSelect As FileDialog
    Dim inputFolder As String
    Dim fileName As String
    Dim wbInput As Workbook
    Dim wsInput As Worksheet
    Dim logRow As Integer
   
    Dim fileType As Variant
   
    Dim HasMergedCells As Boolean
    Dim HasEmptyRows As Boolean
    Dim HasExtraColumn As Boolean
   
    Dim altNamesPA As Variant
    Dim altNamesInv As Variant
   
    altNamesPA = Array("PA (YTD)", "PA (YTD) (Carry Broken Out)", "PA YTD", "PA (YTD)")
    altNamesInv = Array("Inv. Summary", "Invst. Summary", "Investment Rollforward YTD")
    altNamesBS = Array("Balance Sheet", "BS", "BalanceSheet")
   
    ' select directory for processing
    Set folderSelect = Application.FileDialog(msoFileDialogFolderPicker)
    With folderSelect
        .Title = "Select a Folder"
        .AllowMultiSelect = False
        .InitialFileName = ThisWorkbook.path
        If .Show <> -1 Then GoTo EndOfSub
        inputFolder = .SelectedItems(1)
    End With
   
    ' loop through Excel files in selected directory
    logRow = 1
    fileName = Dir(inputFolder & "\*.xl*")
   
    If Len(fileName) = 0 Then
        MsgBox "No *.xl files found in selected folder."
        GoTo EndOfSub
    End If
       
    Do While Len(fileName) > 0
        Set wbInput = Workbooks.Open(inputFolder & "\" & fileName)
        For Each fileType In Array("PA", "BS", "Inv.")
           
            ' select the proper sheet, checking for alternative names and changing sheet name accordingly
            If fileType = "PA" Then
                For Each altName In altNamesPA
                    If WorksheetExists(altName, wbInput) Then
                        Set wsInput = wbInput.Sheets(altName)
                        wsInput.Name = "PA (YTD)"
                        GoTo FixSheet
                    End If
                Next altName
            ElseIf fileType = "BS" Then ' Simple case: no alternative names for this
                For Each altName In altNamesBS
                    If WorksheetExists(altName, wbInput) Then
                        Set wsInput = wbInput.Sheets(altName)
                        wsInput.Name = "BS"
                        GoTo FixSheet
                    End If
                Next altName
            ElseIf fileType = "Inv." Then
                For Each altName In altNamesInv
                    If WorksheetExists(altName, wbInput) Then
                        Set wsInput = wbInput.Sheets(altName)
                        wsInput.Name = "Inv. Summary"
                        GoTo FixSheet
                    End If
                Next altName
            End If
           
            ' If you still haven't met a goto at this point, then the sheet wasn't found: skip and log
            Call LogChange("Unable to find a '" & fileType & "' filetype.", wbInput.Sheets(1))
            GoTo EndOfFileTypeLoop
FixSheet:
            ' Unmerge all cells and copy values
            HasMergedCells = False
            For Each Rng In wsInput.UsedRange
                If Rng.MergeCells Then
                    HasMergedCells = True
                    With Rng.MergeArea
                        .UnMerge
                        .Formula = Rng.Formula
                    End With
                End If
            Next
            If HasMergedCells Then
                Call LogChange("Cells unmerged!", wsInput)
            End If
           
            ' Delete empty top rows
            HasEmptyRows = False
            For i = 1 To 10
                If wsInput.Cells(1, 1) <> "Legal Entity" And wsInput.Cells(1, 1) <> "Fund" Then
                    HasEmptyRows = True
                    wsInput.Rows(1).Delete
                Else
                    Exit For
                End If
            Next i
            If HasEmptyRows Then
                Call LogChange("Top row(s) deleted!", wsInput)
            End If
           
            ' Remove/rename extra columns
            If fileType = "PA" Then
                Call DeleteColumnIfExists("Vehicle", wsInput)
                Call DeleteColumnIfExists("Carry Accrual - Unrealized", wsInput)
                Call DeleteColumnIfExists("Deferred Tax Expense", wsInput)
                Call RenameColumnIfExists("Carry Accrual - Realized", "Carry Accrual", wsInput)
                Call RenameColumnIfExists("Management / Drawdown Fees", "Management Fee", wsInput)
                ' In some files, the "net investor irr" column is duplicated at the end: remove one if there are 2
                If Application.WorksheetFunction.CountIf(wsInput.Rows(1), "Net Investor IRR") = 2 Then
                    Call DeleteColumnIfExists("Net Investor IRR", wsInput)
                End If
            End If
           
            If fileType = "Inv." Then
                Call AddColumnIfDoesntExist("Deal Commitment", 4, wsInput)
                Call AddColumnIfDoesntExist("Unfunded Deal Commitment", 7, wsInput)
            End If
           
            Call ValidateFormat(wsInput, CStr(fileType))
EndOfFileTypeLoop:
        Next fileType
       
        ' Save a copy if any changes were made
        If Not wbInput.Saved Then
            With CreateObject("Scripting.FileSystemObject")
                Dim path As String
               
                path = wbInput.path & "\updated\"
               
                If Not .FolderExists(path) Then
                    .CreateFolder path
                End If
            End With
           
            wbInput.SaveAs fileName:=path & "UPDATED-" & wbInput.Name ' remove "updated-" ?
        End If
       
        wbInput.Close SaveChanges:=False
       
        fileName = Dir
    Loop

    MsgBox ("Finished! Check log sheet for details.")
   
EndOfSub:
    Application.DisplayAlerts = True
    Application.ScreenUpdating = True
End Sub


Sub LogChange(msg As String, ws As Worksheet, Optional isVerbose As Boolean = True)
    Dim wsLog As Worksheet
    Dim lastRow As Long
    Dim logVerbose As Boolean
   
    logVerbose = ThisWorkbook.Sheets("Cover").Cells(3, 10)
   
    If isVerbose And Not logVerbose Then
        Exit Sub
    End If
   
    Set wsLog = ThisWorkbook.Sheets("Log")
   
    lastRow = wsLog.Cells.SpecialCells(xlCellTypeLastCell).Offset(1, 0).Row
   
    wsLog.Cells(lastRow, 1) = Format(Now, "mm/dd/yyyy HH:mm:ss")
    wsLog.Cells(lastRow, 2) = ws.Parent.Name
    wsLog.Cells(lastRow, 3) = ws.Name
    wsLog.Cells(lastRow, 4) = msg
End Sub

Sub DeleteColumnIfExists(header As String, ws As Worksheet)
    On Error GoTo SubEnd
    ws.Columns(Application.WorksheetFunction.Match(header, ws.Rows(1), 0)).Delete
    Call LogChange("''" & header & "' column deleted!", ws)
SubEnd:
    On Error GoTo 0
End Sub

' This is a stupid function for an edge case: check if the column already exists. If it doesn't, add at the specified index
Sub AddColumnIfDoesntExist(newColumnName As String, colNumber As Long, ws As Worksheet)
    On Error GoTo SubEnd
    If Application.WorksheetFunction.CountIf(ws.Rows(1), newColumnName) > 0 Then
        GoTo SubEnd
    End If

    ws.Columns(colNumber).Insert
    ws.Cells(1, colNumber).Value = newColumnName
SubEnd:
    On Error GoTo 0
End Sub

Sub RenameColumnIfExists(header As String, rename As String, ws As Worksheet)
    On Error GoTo SubEnd
    ws.Cells(1, Application.WorksheetFunction.Match(header, ws.Rows(1), 0)).Value = rename
    Call LogChange("''" & header & "' column renamed to '" & rename & "'!", ws)
SubEnd:
    On Error GoTo 0
End Sub

Sub ValidateFormat(ws As Worksheet, formatType As String)
    Dim expectedColumns As Variant
   
    endDate = ThisWorkbook.Sheets("Cover").Cells(4, 11).Value
    beginningDate = ThisWorkbook.Sheets("Cover").Cells(3, 11).Value

    If formatType = "BS" Then
        expectedColumns = Array("Legal Entity", "GL Account", "Account Type", "Dr/(Cr) amount")
    ElseIf formatType = "PA" Then
        expectedColumns = Array("Fund", "Investor", "Commitment", "Beginning Balance as of *", _
        "Contributions", "Transfers", "Distributions", "Investment Income / (Expenses)", "Operating Expenses", _
        "Management Fee", "Realized Gains / (Losses)", "Unrealized Gains / (Losses)", "Carry Accrual", _
        "Ending Balance as of *", "Unfunded Commitment", "Net Investor IRR")
    ElseIf formatType = "Inv." Then
        expectedColumns = Array("Legal Entity", "Deal Name", "FOF/Direct", "Deal Commitment", _
        "Cost Basis *", "Fair Value *", "Unfunded Deal Commitment", "IRR @ MV")
    Else
        Exit Sub
    End If
   
    For i = 1 To UBound(expectedColumns)
        If InStr(expectedColumns(i - 1), "*") Then
            If Not ws.Cells(1, i) Like expectedColumns(i - 1) Then
                Call LogChange("Failed validation: did not find expected date column: '" & expectedColumns(i - 1) & "' Instead found: '" & ws.Cells(1, i) & "'", ws, False)
                Exit Sub
            End If
        ElseIf ws.Cells(1, i) <> expectedColumns(i - 1) Then
            Call LogChange("Failed validation: did not find expected column: '" & expectedColumns(i - 1) & "' Instead found: '" & ws.Cells(1, i) & "'", ws, False)
            Exit Sub
        End If
    Next i
    If ws.Cells(1, i + 1) <> "" Then
        Call LogChange("Extra columns found at end.", ws, False)
    Else
        Call LogChange("Successfully validated!", ws, False)
    End If
End Sub

' H/T [URL='https://stackoverflow.com/questions/6688131/test-or-check-if-sheet-exists']Test or check if sheet exists[/URL]
Function WorksheetExists(shtName As Variant, Optional wb As Workbook) As Boolean
    Dim sht As Worksheet

    If wb Is Nothing Then Set wb = ThisWorkbook
    On Error Resume Next
    Set sht = wb.Sheets(shtName)
    On Error GoTo 0
    WorksheetExists = Not sht Is Nothing
End Function
```


----------

