Sub Auto_Open()
Dim ComboBox2 As Object
Dim ws As Worksheet
Dim rng As Range
Const cCount As Long = 2
Set ws = ActiveSheet(1)
With ws
Set rng = .Range("H10")
Set ComboBox2 = .Shapes.AddFormControl(xlDropDown, _
Left:=rng.Left, _
Top:=rng.Top, _
Width:=rng.Width, _
Height:=rng.Height)
With ComboBox2
.ControlFormat.DropDownLines = 100
.Name = "myCombo"
End With
With Worksheets(5)
Dim erg As Range: Set erg = .Range("D6", .Range("D" & .Rows.Count) _
.End(xlUp)).Resize(, cCount)
Worksheets(1).ComboBox2.ColumnCount = cCount
Worksheets(1).ComboBox2.List = erg.Value
End With
End Sub
This code is in the workbook.
I am trying to create a combobox when someone opens this file and then have it to be populated from worsheet 5.
Its not happening, nothing is created and im also not getting any errors.
Try using Workbook_Open event instead of Auto_Open event (it exist for backwards compatibility), the code should be placed in ThisWorkbook object.
Private Sub Workbook_Open()
Dim ComboBox2 As Object
Dim ws As Worksheet
Dim rng As Range
Const cCount As Long = 2
Set ws = ActiveSheet 'Avoid using ActiveSheet, replace this with the worksheet name instead
With ws
Set rng = .Range("H10")
Set ComboBox2 = .Shapes.AddFormControl(xlDropDown, _
Left:=rng.Left, _
Top:=rng.Top, _
Width:=rng.Width, _
Height:=rng.Height)
End With
With ComboBox2
.ControlFormat.DropDownLines = 100
.Name = "myCombo"
End With
With Worksheets(5)
Dim erg As Range
Set erg = .Range("D6", .Range("D" & .Rows.Count) _
.End(xlUp)).Resize(, cCount)
End With
With Worksheets(1).ComboBox2
.ColumnCount = cCount
.List = erg.Value
End With
End Sub
Related
Sub all_col()
Workbooks("xlsb file").Worksheets("sheet name").Range("A1:CR1048576").Copy_
Workbooks("xlsx file").Worksheets("sheet name").Range("A1")
How do I write more efficient code to copy all the cell ranges from one worksheet to another within different workbooks.instead of using "A1:CR1048576" is there a better way?
Try using the UsedRange property of the worksheet.
Sub all_col()
wb1.Worksheets("sheet name").UsedRange.Copy _
wb2.Worksheets("sheet name").Range("A1")
End Sub
Copy Worksheet In Closed Workbook to Worksheet in ThisWorkbook
The function is a sub converted to a function to return a boolean indicating whether it was successful i.e. whether no errors occurred.
You could classify this code as an 'import operation': the source workbook is closed, while the destination workbook contains the code. With 'a few changes', you could rewrite this code as an 'export operation': the destination workbook is closed and the source workbook contains the code. Looking at the file extensions, it looks like you needed the latter.
Option Explicit
Sub WsToWsInThisWorkbookTEST()
Dim GotCopied As Boolean: GotCopied = WsToWsInThisWorkbook( _
"C:\Test\Test.xlsx", "Sheet1", "A1", "Sheet1", "A1")
If Not GotCopied Then Exit Sub
'Continue with your code e.g.:
MsgBox "Worksheet got copied.", vbInformation
End Sub
Function WsToWsInThisWorkbook( _
ByVal SourceFilePath As String, _
Optional ByVal SourceSheetID As Variant, _
Optional ByVal SourceFirstCell As String = "A1", _
Optional ByVal DestinationSheetID As Variant = "Sheet1", _
Optional ByVal DestinationFirstCell As String = "A1") _
As Boolean
On Error GoTo ClearError
Const ProcName As String = "WsToWsInThisWorkbook"
' Source
If Len(Dir(SourceFilePath)) = 0 Then
MsgBox "Source file '" & SourceFilePath & "' not found.", vbCritical
Exit Function
End If
Dim swb As Workbook: Set swb = Workbooks.Open(SourceFilePath, True, True)
Dim sws As Worksheet: Set sws = swb.Sheets(SourceSheetID)
Dim srg As Range
With sws.UsedRange
Dim lcell As Range: Set lcell = .Cells(.Rows.Count, .Columns.Count)
Set srg = sws.Range(SourceFirstCell, lcell)
End With
' Destination.
Dim dwb As Workbook: Set dwb = ThisWorkbook ' workbook containing this code
Dim dws As Worksheet: Set dws = dwb.Sheets(DestinationSheetID)
Dim dfCell As Range: Set dfCell = dws.Range(DestinationFirstCell)
' Copy.
srg.Copy dfCell
WsToWsInThisWorkbook = True
ProcExit:
On Error Resume Next
If Not swb Is Nothing Then swb.Close SaveChanges:=False
On Error GoTo 0
Exit Function
ClearError:
MsgBox "Run-time error '" & Err.Number & "':" & vbLf & Err.Description, _
vbCritical, ProcName
Resume ProcExit
End Function
Most of the answers provided would work but UsedRange extends to formatting (see this epic thread] discussing best method to find last row).
If that were an issue, you could include these functions below your original macro and it will be the precise space to copy from:
Sub all_col()
Dim lastRow As Long, lastColumn As Long
With Workbooks("xlsb file").Worksheets("sheet name")
lastRow = FindLastRowInSheet(.Range("A1"))
lastColumn = FindLastColumnInSheet(.Range("A1"))
.Range("A1").Resize(lastRow, lastColumn).Copy_
Workbooks("xlsx file").Worksheets("sheet name").Range ("A1")
End With
End Sub
Function FindLastRowInRange(someColumns As Range) As Long
Const zFx = "=MAX(FILTER(ROW(????),NOT(ISBLANK(????)),0))"
Dim tRng As Range, i As Long, tRow As Long, pRng As Range
With someColumns.Worksheet
Set tRng = Intersect(someColumns.EntireColumn, .UsedRange)
For i = 1 To tRng.Columns.Count
Set pRng = Intersect(tRng.Columns(i), _
Range(.Rows(FindLastRowInRange + 1), .Rows(.Rows.Count)))
If Not pRng Is Nothing Then
tRow = .Evaluate(Replace(zFx, "????", _
pRng.Address, 1, -1))
If tRow > FindLastRowInRange Then _
FindLastRowInRange = tRow
End If
Next i
End With
End Function
Function FindLastRowInSheet(anywhereInSheet As Range) As Long
FindLastRowInSheet = FindLastRowInRange(anywhereInSheet.Worksheet.UsedRange)
End Function
Function findLastColumn(someRows As Range) As Long
Const zFx = "=MAX(FILTER(COLUMN(????),NOT(ISBLANK(????)),0))"
Dim tRng As Range, i As Long, tRow As Long, pRng As Range
With someRows.Worksheet
Set tRng = Intersect(.UsedRange, someRows.EntireRow)
For i = 1 To tRng.Rows.Count
Set pRng = Intersect(tRng.Rows(i), Range(.Rows(.Columns.Count), .Rows(findLastColumn + 1)))
If Not pRng Is Nothing Then
tRow = .Evaluate(Replace(zFx, "????", _
pRng.Address, 1, -1))
If tRow > findLastColumn Then _
findLastColumn = tRow
End If
Next i
End With
End Function
Function FindLastColumnInSheet(anywhereInSheet As Range) As Long
FindLastColumnInSheet = findLastColumn(anywhereInSheet.Worksheet.UsedRange)
End Function
This block of code was working fine but I deleted some lines above Find() that broke it. Any ideas?
Sub CopySheet()
Dim TotalRow As Integer
Set NurselineBook = ThisWorkbook
TotalRow = Range("$C:$C").Find(What:="Grand Total", LookIn:=xlValues, LookAt:=xlWhole).Row
Range("A1:L" & TotalRow).Select
Range("Ah1").Activate
Selection.CopyPicture Appearance:=xlScreen, Format:=xlBitmap
MsgBox "Dashboard Copied"
End Sub
Sub CopyTable()
Const wsName As String = "Sheet1"
Const ColumnsAddress As String = "A:L"
Const FirstRow As Long = 1
Const CriteriaColumn As Long = 3
Const gtString As String = "Grand Total"
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim ws As Worksheet: Set ws = wb.Worksheets(wsName)
Dim srg As Range
With ws.Columns(ColumnsAddress)
Set srg = .Resize(ws.Rows.Count - FirstRow + 1).Offset(FirstRow - 1)
End With
Dim gtcell As Range: Set gtcell = srg.Columns(CriteriaColumn) _
.Find(gtString, , xlValues, xlWhole, , xlPrevious)
If gtcell Is Nothing Then
MsgBox "Could not find '" & gtString & "'.", vbCritical
Exit Sub
End If
Dim drg As Range
Set drg = srg.Resize(gtcell.Row - FirstRow + 1)
drg.CopyPicture Appearance:=xlScreen, Format:=xlBitmap
MsgBox "Dashboard Copied", vbInformation
End Sub
When I try to export the Sheets to pdf. All of them are split because they are too wide. How can you prevent that from happening? I've searched for something like disabling page break, but I could not implement it correctly perhaps someone knows how. Or setting the range is maybe also a possiblity. Would really like some help.
There are multiple sheets
Thank you guys!
Option Explicit
Sub FilterData()
'DMT32 2017
Dim ws1Master As Worksheet, wsNew As Worksheet, wsFilter As Worksheet
Dim Datarng As Range, FilterRange As Range, objRange As Range
Dim rowcount As Long
Dim colcount As Integer, FilterCol As Integer, FilterRow As Long
Dim SheetName As String, msg As String
'master sheet
Set ws1Master = ActiveSheet
'select the Column filtering
top:
On Error Resume Next
Set objRange = Application.InputBox("Select Field Name To Filter", "Range Input", , , , , , 8)
On Error GoTo 0
If objRange Is Nothing Then
Exit Sub
ElseIf objRange.Columns.Count > 1 Then
GoTo top
End If
FilterCol = objRange.Column
FilterRow = objRange.Row
With Application
.ScreenUpdating = False
.DisplayAlerts = False
End With
On Error GoTo progend
'add filter sheet
Set wsFilter = Sheets.Add
With ws1Master
.Activate
.Unprotect Password:="" 'add password if needed
rowcount = .Cells(.Rows.Count, FilterCol).End(xlUp).Row
colcount = .Cells(FilterRow, .Columns.Count).End(xlToLeft).Column
If FilterCol > colcount Then
Err.Raise 65000, "", "FilterCol Setting Is Outside Data Range.", "", 0
End If
Set Datarng = .Range(.Cells(FilterRow, 1), .Cells(rowcount, colcount))
'extract Unique values from FilterCol
.Range(.Cells(FilterRow, FilterCol), .Cells(rowcount, FilterCol)).AdvancedFilter _
Action:=xlFilterCopy, CopyToRange:=wsFilter.Range("A1"), Unique:=True
rowcount = wsFilter.Cells(wsFilter.Rows.Count, "A").End(xlUp).Row
'set Criteria
wsFilter.Range("B1").Value = wsFilter.Range("A1").Value
For Each FilterRange In wsFilter.Range("A2:A" & rowcount)
'check for blank cell in range
If Len(FilterRange.Value) > 0 Then
'add the FilterRange to criteria
wsFilter.Range("B2").Value = FilterRange.Value
'ensure tab name limit not exceeded
SheetName = Trim(Left(FilterRange.Value, 31))
'check if sheet exists
On Error Resume Next
Set wsNew = Worksheets(SheetName)
If wsNew Is Nothing Then
'if not, add new sheet
Set wsNew = Sheets.Add(after:=Worksheets(Worksheets.Count))
wsNew.Name = SheetName
Else
'clear existing data
wsNew.UsedRange.ClearContents
End If
On Error GoTo progend
'apply filter
Datarng.AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=wsFilter.Range("B1:B2"), _
CopyToRange:=wsNew.Range("A1"), Unique:=False
End If
wsNew.UsedRange.Columns.AutoFit
Set wsNew = Nothing
Next
.Select
End With
progend:
wsFilter.Delete
With Application
.ScreenUpdating = True: .DisplayAlerts = True
End With
If Err > 0 Then MsgBox (Error(Err)), 16, "Error"
End Sub
Sub SaveAsPDF()
Dim ws As Worksheet
For Each ws In Worksheets
ws.ExportAsFixedFormat xlTypePDF, "C:\PDF\" & ws.Name & ".pdf"
Next ws
End Sub
I convert multiple ranges on different worksheets to a single PDF.
Private Sub CommandButton1_Click()
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim vFile As Variant
Dim sFile As String
Set ws1 = Worksheets("Sheet1")
ws1.PageSetup.PrintArea = "B2:K51"
Set ws2 = Worksheets("Sheet2")
ws2.PageSetup.PrintArea = "A3:J52, J3:S52, S3:AE52"
Worksheets(Array(ws1.Name, ws2.Name)).Select
ActiveSheet.ExportAsFixedFormat _
Type:=xlTypePDF, _
Filename:=vFile, _
Quality:=xlQualityStandard, _
IncludeDocProperties:=True, _
IgnorePrintAreas:=False, _
OpenAfterPublish:=False
MsgBox "PDF file has been created."
End If
End Sub
The PrintArea range for ws2 creates a single range.
How do I separate the ranges so the output is three ranges instead of one?
Export to PDF
The solution inserts a new worksheet and copies the ranges to it. Then it exports the new worksheet to PDF and deletes the new worksheet.
Sheet Module e.g. Sheet1 (where the command button is)
Option Explicit
Private Sub CommandButton1_Click()
exportToPDF
End Sub
Standard Module e.g. Module1
Option Explicit
Sub exportToPDF()
' Define constants.
Const Gap As Long = 0
Const vFile As String = "F:\Test\Export.pdf"
Dim Ranges1 As Variant
Ranges1 = Array("B2:K51")
Dim Ranges2 As Variant
Ranges2 = Array("A3:J52", "J3:S52", "S3:AE52")
' Define workbook.
Dim wb As Workbook
Set wb = ThisWorkbook ' The workbook containing this code.
' Define worksheets.
Dim ws1 As Worksheet
Set ws1 = Worksheets("Sheet1")
Dim ws2 As Worksheet
Set ws2 = Worksheets("Sheet2")
Dim ws3 As Worksheet
Set ws3 = wb.Worksheets.Add(After:=wb.Sheets(wb.Sheets.Count))
' Copy ranges from first to third worksheet.
Dim rng As Range
Dim CurrRow As Long
CurrRow = 1
Dim j As Long
Dim RowsCount As Long
Dim ColsCount As Long
For j = LBound(Ranges1) To UBound(Ranges1)
Set rng = ws1.Range(Ranges1(j))
rng.Copy
ws3.Cells(CurrRow, 1).PasteSpecial xlPasteValues
ws3.Cells(CurrRow, 1).PasteSpecial xlFormats
If ColsCount < rng.Columns.Count Then
ColsCount = rng.Columns.Count
End If
CurrRow = CurrRow + rng.Rows.Count + Gap
Next j
' Copy ranges from second to third worksheet.
For j = LBound(Ranges2) To UBound(Ranges2)
Set rng = ws2.Range(Ranges2(j))
rng.Copy
ws3.Cells(CurrRow, 1).PasteSpecial xlPasteValues
ws3.Cells(CurrRow, 1).PasteSpecial xlFormats
If ColsCount < rng.Columns.Count Then
ColsCount = rng.Columns.Count
End If
CurrRow = CurrRow + rng.Rows.Count + Gap
Next j
' Export and close third worksheet.
With ws3
Set rng = .Range("A1").Resize(CurrRow - Gap - 1, ColsCount)
rng.Columns.AutoFit
.PageSetup.PrintArea = rng.Address
.ExportAsFixedFormat Type:=xlTypePDF, _
Filename:=vFile, _
Quality:=xlQualityStandard, _
IncludeDocProperties:=False, _
IgnorePrintAreas:=False, _
OpenAfterPublish:=True
Application.DisplayAlerts = False
.Delete
Application.DisplayAlerts = True
End With
' Inform user.
MsgBox "PDF file has been created."
End Sub
Populate Data (Standard Module)
To quickly see what the code does:
Create a workbook containing worksheets Sheet1 and Sheet2.
Copy all three codes appropriately.
Run populateData.
Run exportPDF.
The Code
Private Sub populateData()
With [Sheet1!B2:K51]
.Formula = "=ROW()&""|""&COLUMN()"
.Interior.ColorIndex = 6
End With
With [Sheet2!A3:AE52]
.Formula = "=ROW()&""|""&COLUMN()"
.Interior.ColorIndex = 8
End With
End Sub
What is the most reliable and efficient way to trim all sheets of an Excel file of empty formatting?
I consider the Used Range to be all cells with visible data and objects, excluding Comments.
Reliability aspects:
Preserve all visible data (with its formatting) and formulas on all sheets
Preserve objects on all sheets: charts, pivot tables, and list objects (data tables)
Graphics to remain exactly the same position, size and all other properties after the cleanup
Remove all blank cells with old formatting or empty strings that generate a "false" Used Range
These can be cells that were previously used but their data was removed
Invalid formulas, or invisible characters like an untrimmed strings or carriage returns
The solution should also remove all invalid Names (containing the string "#REF!")
Cleanup conditional formatting rules on all sheets removing duplicate rules for the same columns
Clean excess formatting on workbooks and sheets unprotected or protected without a password
A solution with more coverage than the one provided by Microsoft on this page
How to reset the last cell in Excel
The code in the Excel Add-in available in this answer
I'm providing my own attempt to cover the requirements, as a reference
Paste code in a new VBA module and run the first procedure (trimXL)
.
Option Explicit
Private pb01 As Boolean, pb02 As Boolean 'protected attribs of WB & WS
Private ps01 As Boolean, ps02 As Boolean, ps03 As Boolean, ps04 As Boolean
Private ps05 As Boolean, ps06 As Boolean, ps07 As Boolean, ps08 As Boolean
Private ps09 As Boolean, ps10 As Boolean, ps11 As Boolean, ps12 As Boolean
Private ps13 As Boolean, ps14 As Boolean, ps15 As Boolean, ps16 As Boolean
Private isWBProtected As Boolean
Private shapeInfo As Object
Public Function trimXL() As Boolean
Dim wb As Workbook, ws As Worksheet, sCnt As Long, shapesOnWS As Long
Dim lastCel As Range, urAll As Range, thisActWS As Worksheet, isGo As Boolean
Dim lrAll As Long, lcAll As Long, lrDat As Long, lcDat As Long, msg As String
Dim emptyRows As Range, emptyCols As Range, sz1 As Single, sz2 As Single
enableXL False
Set wb = ThisWorkbook
If wbIsReady(wb) Then
Set thisActWS = wb.ActiveSheet
removeInvalidNames
sz1 = FileLen(wb.FullName) / 1024
For Each ws In wb.Worksheets
isGo = IIf(isWBProtected, canUnprotectWs(ws), True)
If isGo Then
Set urAll = ws.UsedRange
lrAll = urAll.Rows.Count + urAll.Row - 1
lcAll = urAll.Columns.Count + urAll.Column - 1
If 0 Then unhideRows ws, urAll
removeXLErrors ws.UsedRange
trimWhiteSpaces ws
Set shapeInfo = newDictionary
shapesOnWS = persistShapesInfo(ws)
trimListObjects ws
Set lastCel = GetMaxCell(urAll)
lrDat = lastCel.Row
lcDat = lastCel.Column
Set emptyRows = ws.Range(ws.Cells(lrDat + 1, 1), ws.Cells(lrAll + 1, 1))
Set emptyCols = ws.Range(ws.Cells(1, lcDat + 1), ws.Cells(1, lcAll + 1))
'setStandardSize ws, emptyRows, emptyCols
If (lrDat = 1 And lcDat = 1) Or (lrAll <> lrDat Or lcAll <> lcDat) Then
If lrDat = 1 And lcDat = 1 And Len(lastCel.Value2) = 0 Then
urAll.EntireRow.Delete
If lrAll <> lrDat Or lcAll <> lcDat Then sCnt = sCnt + 1
Else
If lrAll <> lrDat Or lcAll <> lcDat Then
If lrAll <> lrDat Then emptyRows.EntireRow.Delete
If lcAll <> lcDat Then emptyCols.EntireColumn.Delete
sCnt = sCnt + 1
End If
End If
End If
If shapesOnWS > 0 Then resetShapesInfo ws
'resetConditionalFormatting
If isWBProtected Then protectWs ws
End If
Next
activateFirstCell ws
thisActWS.Activate
If isWBProtected Then protectWB wb
sz2 = FileLen(wb.FullName) / 1024
'wb.Save
Set thisActWS = Nothing
Set shapeInfo = Nothing
End If
enableXL
msg = msg & " File '" & wb.Name & "' cleaned" & vbNewLine & vbNewLine
msg = msg & " Size" & vbTab & "Before: " & vbTab & sz1 & " Kb" & vbNewLine
msg = msg & vbTab & " After: " & vbTab & sz2 & " Kb" & vbNewLine & vbNewLine
msg = msg & vbTab & "Trimmed Sheets" & vbTab & sCnt & vbTab & vbNewLine & vbNewLine
MsgBox msg, vbInformation, " Trim Completed: """ & wb.Name & """"
End Function
'Sheet Functions -----------------------------------------------------------------------
Private Sub activateFirstCell(ByRef ws As Worksheet)
If ws Is Nothing Then Set ws = ThisWorkbook.ActiveSheet
Application.Goto ws.Cells(1), True
'ws.Activate: ws.Cells(1).Activate
End Sub
Private Sub setStandardSize(ByRef ws As Worksheet, ByRef eRows As Range, eCols As Range)
eRows.EntireColumn.ColumnWidth = ws.StandardWidth
eCols.EntireColumn.ColumnWidth = ws.StandardWidth
eRows.EntireRow.RowHeight = ws.StandardHeight
eCols.EntireRow.RowHeight = ws.StandardHeight
End Sub
Public Sub unhideRows(ByRef ws As Worksheet, ByRef rng As Range)
If ws Is Nothing Then Set ws = ThisWorkbook.ActiveSheet
If rng Is Nothing Then Set rng = ws.UsedRange
If Not ws.AutoFilter Is Nothing Then
With ws.AutoFilter
If .FilterMode Then If .Filters.Count = 1 Then rng.AutoFilter
End With
End If
rng.Rows.EntireRow.Hidden = False
rng.Columns.EntireColumn.Hidden = False
End Sub
Public Function GetMaxCell(Optional ByRef rng As Range = Nothing) As Range
'It returns the last cell of range with data, or A1 if Worksheet is empty
Const NONEMPTY As String = "*"
Dim lRow As Range, lCol As Range
If rng Is Nothing Then Set rng = Application.ThisWorkbook.ActiveSheet.UsedRange
If WorksheetFunction.CountA(rng) = 0 Then
Set GetMaxCell = rng.Parent.Cells(1, 1)
Else
With rng
Set lRow = .Cells.Find(What:=NONEMPTY, LookIn:=xlFormulas, _
after:=.Cells(1, 1), _
SearchDirection:=xlPrevious, _
SearchOrder:=xlByRows)
Set lCol = .Cells.Find(What:=NONEMPTY, LookIn:=xlFormulas, _
after:=.Cells(1, 1), _
SearchDirection:=xlPrevious, _
SearchOrder:=xlByColumns)
Set GetMaxCell = .Parent.Cells(lRow.Row, lCol.Column)
End With
End If
End Function
Public Sub trimWhiteSpaces(ByRef ws As Worksheet) 'Blanks ----------------------------
Dim i As Byte
With ws.UsedRange
For i = 1 To 10
.Replace What:=Space(i), Replacement:=vbNullString, LookAt:=xlWhole
Next
.Replace What:=vbTab, Replacement:=vbNullString, LookAt:=xlWhole
.Replace What:=vbCrLf, Replacement:=vbNullString, LookAt:=xlWhole
.Replace What:=vbCr, Replacement:=vbNullString, LookAt:=xlWhole
.Replace What:=vbLf, Replacement:=vbNullString, LookAt:=xlWhole
.Replace What:=vbNewLine, Replacement:=vbNullString, LookAt:=xlWhole
.Replace What:=vbNullChar, Replacement:=vbNullString, LookAt:=xlWhole
.Replace What:=vbBack, Replacement:=vbNullString, LookAt:=xlWhole
.Replace What:=vbFormFeed, Replacement:=vbNullString, LookAt:=xlWhole
.Replace What:=vbVerticalTab, Replacement:=vbNullString, LookAt:=xlWhole
.Replace What:=vbObjectError, Replacement:=vbNullString, LookAt:=xlWhole
End With
End Sub
Public Sub trimListObjects(ByRef ws As Worksheet) 'tables
Dim tbl As ListObject, lastCel As Range, lrDat As Long, lcDat As Long
For Each tbl In ws.ListObjects
With tbl
lcDat = .ListColumns.Count
If .Range.Count <> (.ListRows.Count * lcDat) Then
Set lastCel = GetMaxCell(.Range)
lrDat = lastCel.Row - .Range.Row + 1
If lrDat = 1 Then .Delete Else .Resize .Range.Resize(lrDat + 1, lcDat)
End If
End With
Next
End Sub
Public Sub removeXLErrors(ByRef ur As Range) 'All errors ----------------------------
Dim i As Byte, xlError() As String
On Error Resume Next
ur.SpecialCells(xlCellTypeFormulas, xlErrors).Clear
If 0 Then
ReDim xlError(6)
xlError(0) = "#DIV/0!" 'Excel.XlCVError.xlErrDiv0 = 2007 => #DIV/0!
xlError(1) = "#N/A" 'Excel.XlCVError.xlErrNA = 2042 => #N/A
xlError(2) = "#NAME?" 'Excel.XlCVError.xlErrName = 2029 => #NAME?
xlError(3) = "#NULL" 'Excel.XlCVError.xlErrNull = 2000 => #NULL
xlError(4) = "#NUM!" 'Excel.XlCVError.xlErrNum = 2036 => #NUM!
xlError(5) = "#REF" 'Excel.XlCVError.xlErrRef = 2023 => #REF
xlError(6) = "#VALUE!" 'Excel.XlCVError.xlErrValue = 2015 => #VALUE!
'VBA.Conversion.CVErr 1 / 0
'Public Const EXCEL_ERROR As String = "#N/A"
For i = 0 To 6
ur.Replace What:=xlError(i), Replacement:=vbNullString, LookAt:=xlWhole
Next
End If
End Sub
Public Sub resetConditionalFormatting(Optional ByRef rng As Range = Nothing)
Const F_ROW As Long = 2
Dim ws As Worksheet, ur As Range, maxCol As Long, maxRow As Long, thisCol As Long
Dim colRng As Range, fcCol As Range, fcCount As Long, fcAdr As String
If rng Is Nothing Then Set rng = Application.ThisWorkbook.ActiveSheet.UsedRange
Set ws = ThisWorkbook.ActiveSheet
Set ur = ws.UsedRange
maxRow = ur.Rows.Count
maxCol = ur.Columns.Count
For Each colRng In ws.Columns
If colRng.Column > maxCol Then Exit For
thisCol = thisCol + 1
Set fcCol = ws.Range(ws.Cells(F_ROW, thisCol), ws.Cells(maxRow, thisCol))
With colRng.FormatConditions
If .Count > 0 Then
fcCount = 1
fcAdr = .Item(fcCount).AppliesTo.Address
While fcCount <= .Count
If .Item(fcCount).AppliesTo.Address = fcAdr Then
.Item(fcCount).ModifyAppliesToRange fcCol
fcCount = fcCount + 1
Else
On Error Resume Next
.Item(fcCount).Delete
End If
Wend
End If
End With
Next
End Sub
'Workbook Functions --------------------------------------------------------------------
Public Sub removeInvalidNames()
Dim itm As Name
With ThisWorkbook
If .Names.Count > 0 Then
On Error Resume Next
Err.Clear
For Each itm In .Names
If InStr(itm.RefersTo, "#REF!") > 0 Then itm.Delete
Next
End If
'xlResetSettings
.Saved = True
End With
End Sub
'Shape Functions -----------------------------------------------------------------------
Public Function newDictionary(Optional ByRef dictObj As Object, _
Optional ByVal caseSensitive As Boolean = False) As Object
If Not dictObj Is Nothing Then Set dictObj = Nothing
'Set dictionaryObject = New Dictionary
Set dictObj = CreateObject("Scripting.Dictionary")
dictObj.CompareMode = IIf(caseSensitive, vbBinaryCompare, vbTextCompare)
Set newDictionary = dictObj
End Function
Private Function persistShapesInfo(ByRef ws As Worksheet) As Long
Dim sh As Shape, totalShapes As Long
For Each sh In ws.Shapes
If Not sh.Type = msoComment Then
With sh
shapeInfo(.Name) = .Top & "|" & .Left & "|" & .Height & "|" & .Width
shapeInfo(.Name) = shapeInfo(.Name) & "|" & .Placement
.Placement = xlFreeFloating
End With
totalShapes = totalShapes + 1
End If
Next
persistShapesInfo = totalShapes
End Function
Private Sub resetShapesInfo(ByRef ws As Worksheet)
Dim sh As Variant, shInfo As Variant
For Each sh In shapeInfo
shInfo = Split(shapeInfo(sh), "|")
With ws.Shapes(sh)
.Top = shInfo(0)
.Left = shInfo(1)
.Height = shInfo(2)
.Width = shInfo(3)
.Placement = shInfo(4)
End With
Next
End Sub
'Excel Functions -----------------------------------------------------------------------
Public Sub enableXL(Optional ByVal opt As Boolean = True)
With Application
.Calculation = IIf(opt, xlCalculationAutomatic, xlCalculationManual)
.DisplayAlerts = opt
.DisplayStatusBar = opt
.EnableAnimations = opt
.EnableEvents = opt
.ScreenUpdating = opt
End With
enableWS , opt
End Sub
Public Sub enableWS(Optional ByVal ws As Worksheet, Optional ByVal opt As Boolean =True)
If ws Is Nothing Then
For Each ws In Application.ActiveWorkbook.Sheets
setWS ws, opt
Next
Else
setWS ws, opt
End If
End Sub
Private Sub setWS(ByVal ws As Worksheet, Optional ByVal opt As Boolean = True)
With ws
.DisplayPageBreaks = False
.EnableCalculation = opt
.EnableFormatConditionsCalculation = opt
.EnablePivotTable = opt
End With
End Sub
Public Sub xlResetSettings() 'default Excel settings
With Application
.Calculation = xlCalculationAutomatic
.DisplayAlerts = True
.DisplayStatusBar = True
.EnableAnimations = False
.EnableEvents = True
.ScreenUpdating = True
Dim sh As Worksheet
For Each sh In Application.ActiveWorkbook.Sheets
With sh
.DisplayPageBreaks = False
.EnableCalculation = True
.EnableFormatConditionsCalculation = True
.EnablePivotTable = True
End With
Next
End With
End Sub
'Protection Functions ------------------------------------------------------------------
Private Function wbIsReady(ByRef wb As Workbook) As Boolean
isWBProtected = wbIsProtected(wb)
wbIsReady = canUnprotectWb(wb)
End Function
Private Function wbIsProtected(ByRef wb As Workbook) As Boolean
Dim hasPassword As Boolean, ws As Worksheet
If Not wb.ReadOnly Then
pb01 = wb.ProtectStructure
pb02 = wb.ProtectWindows
hasPassword = pb01 Or pb02
For Each ws In wb.Worksheets
hasPassword = hasPassword Or wsIsProtected(ws)
If hasPassword Then Exit For
Next
End If
wbIsProtected = hasPassword
End Function
Private Function wsIsProtected(ByRef ws As Worksheet) As Boolean
With ws
ps01 = .ProtectContents
ps02 = .ProtectDrawingObjects
With .Protection
ps03 = .AllowDeletingColumns
ps04 = .AllowDeletingRows
ps05 = .AllowEditRanges.Count > 0
ps06 = .AllowFiltering
ps07 = .AllowFormattingCells
ps08 = .AllowFormattingColumns:
ps09 = .AllowFormattingRows
ps10 = .AllowInsertingColumns
ps11 = .AllowInsertingHyperlinks
ps12 = .AllowInsertingRows
ps13 = .AllowSorting
ps14 = .AllowUsingPivotTables
End With
ps15 = .ProtectionMode
ps16 = .ProtectScenarios
End With
wsIsProtected = ps01 Or ps02 Or ps03 Or ps04 Or ps05 Or ps06 Or ps07 Or ps08 Or _
ps09 Or ps10 Or ps11 Or ps12 Or ps13 Or ps14 Or ps15 Or ps16
End Function
Private Sub protectWB(ByRef wb As Workbook)
If Not wb.ReadOnly Then wb.Protect vbNullString, pb01, pb02
End Sub
Private Sub protectWs(ByRef ws As Worksheet)
ws.Protect vbNullString, ps02, ps01, ps16, True, ps07, ps08, _
ps09, ps10, ps12, ps11, ps03, ps04, ps13, ps06, ps14
End Sub
Private Function canUnprotectWb(ByRef wb As Workbook) As Boolean
Dim hasPassword As Boolean
hasPassword = True
On Error Resume Next
wb.Unprotect vbNullString
If Err.Number = 1004 Then
Err.Clear
hasPassword = True
End If
canUnprotectWb = hasPassword
End Function
Private Function canUnprotectWs(ByRef ws As Worksheet) As Boolean
Dim hasPassword As Boolean
hasPassword = True
On Error Resume Next
ws.Unprotect vbNullString
If Err.Number = 1004 Then
Err.Clear
hasPassword = False
End If
canUnprotectWs = hasPassword
End Function
More details about cleaning up conditional formatting rules in this SO answer