I have been working on automating different parts of the process of formatting a very large data set. I am stuck on trying to automate the "remove duplicates" command across all blocks of my data:
I have blocks of data (9 columns wide, x rows long) as on the image attached. In the column called "#Point ID" are values 0-n. Some values appear once, some values appear more than once. Different blocks have different "#Point ID" columns
I would like to delete all rows in the block where the value in the "#Point ID" column has already occurred (starting from the top, moving down the rows). I would like the deleted rows removed from the blocks, so only the rows (which are blue on the image) with unique values in "#Point ID" column (green on the image) remain.
I have found VBA modules that work on a single block, but I don't know how to make it function across all my blocks. Delete rows in Excel based on duplicates in Column
I have also tried combinations of functions (inc. UNIQUE and SORTBY) without any success.
What's a function or a VBA module that works?
Use this
Public Sub cleanBlock(rng As Range)
Dim vals As Object
Set vals = CreateObject("Scripting.Dictionary")
Dim R As Range
Dim adds As Range
For Each R In rng.Rows
If (vals.exists(R.Cells(1, 2).Value)) Then
If adds Is Nothing Then
Set adds = R
Else
Set adds = Union(adds, R)
End If
Else
vals(R.Cells(1, 2).Value) = True
End If
Next R
Debug.Print (adds.Address)
If Not adds Is Nothing Then adds.Delete shift:=xlUp
Set vals = Nothing
End Sub
Public Sub test()
cleanBlock Range("b3:j20")
cleanBlock Range("l3:t20")
cleanBlock Range("y3:ad20")
End Sub
Remove Duplicates in Areas of a Range
Sub RemoveDupesByAreas()
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim ws As Worksheet: Set ws = wb.Sheets("Sheet1") ' adjust!
Dim rg As Range: Set rg = ws.UsedRange.SpecialCells(xlCellTypeConstants)
Dim aCount As Long: aCount = rg.Areas.Count
Dim arg As Range, a As Long
For a = aCount To 1 Step -1
Set arg = rg.Areas(a)
Debug.Print a, arg.Address(0, 0)
' Before running the code with the next line, in the Immediate
' window ('Ctrl+G'), carefully check if the range addresses
' match the areas of your data. If they match, uncomment
' the following line to apply remove duplicates.
'arg.RemoveDuplicates 2, xlYes
Next a
MsgBox "Duplicates removed.", vbInformation
End Sub
Find and FindNext feat. CurrentRegion
Sub RemoveDupesByFind()
Const SEARCH_STRING As String = "Source.Name"
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim ws As Worksheet: Set ws = wb.Sheets("Sheet1") ' adjust!
Dim rg As Range: Set rg = ws.UsedRange
Dim fCell As Range: Set fCell = rg.Find( _
SEARCH_STRING, , xlFormulas, xlWhole, xlByRows, xlPrevious)
If fCell Is Nothing Then
MsgBox """" & SEARCH_STRING & """ not found.", vbCritical
Exit Sub
End If
Dim FirstAddress As String: FirstAddress = fCell.Address
Do
fCell.CurrentRegion.RemoveDuplicates 2, xlYes
Set fCell = rg.FindNext(fCell)
Loop Until fCell.Address = FirstAddress
MsgBox "Duplicates removed.", vbInformation
End Sub
Another way, maybe something like this :
Sub test()
Dim rgData As Range
Dim rg As Range: Dim cell As Range
Dim rgR As Range: Dim rgDel As Range
Set rgData = Sheets("Sheet1").UsedRange 'change as needed
Set rgData = rgData.Resize(rgData.Rows.Count - 1, rgData.Columns.Count).Offset(1, 0)
For Each rg In rgData.SpecialCells(xlConstants).Areas
For Each cell In rg.Columns(2).Cells
Set rgR = cell.Offset(0, -1).Resize(1, rg.Columns.Count)
If cell.Value = 0 And cell.Offset(1, 0).Value <> 0 And cell.Offset(0, 1).Value = 0 And cell.Address = rg.Columns(2).Cells(1, 1).Address Then
Else
If Application.CountIf(rg.Columns(2), cell.Value) > 1 And cell.Offset(0, 1).Value = 0 Then
If rgDel Is Nothing Then Set rgDel = rgR Else Set rgDel = Union(rgDel, rgR)
End If
End If
Next cell
Next rg
rgDel.Delete Shift:=xlUp
End Sub
The code assumed that there'll be no blank cell within each block and there will be full blank column (no value at all) between each block. So it sets the usedrange as rgData variable, and loop to each area/block in rgData as rg variable.
Within rg, it loop to each cell in rg column 2, and check if the count of the looped cell value is > 1 and the value of the looped cell.offset(0,1) is zero, then it collect the range as rgDel variable.
Then finally it delete the rgDel.
If you want to step run the code, try to add something like this rg.select ... rgR.select .... after the variable is set. For example, add rgDel.select right before next area, so you can see what's going on.
The code assume that :
the first value right under "#Point" in each block will be always zero. It will
never happen that the value is other than zero.
the next value (after that zero value) is maybe zero again or maybe one.
if there are duplicates (two same value) in column #Point then in column X, it's not fix that the first one will always have value and the second one will always zero value.
If the data is always fix that the first one will always have value and the second one will always zero value (if there are duplicate), I suggest you to use Mr. VBasic2008 or Mr. wrbp answer. Thank you.
Related
I am trying to find all values greater than 6 in the Rep column, delete the entire row, and insert a blank row.
I tried For Each Next loop, With and Do While. The dataset has over 5000 rows so I chose the column as range but it won't go to the next or the app crashes.
I searched the internet but there are few useful sources for what I'm trying to do. The code I have is a mash of approaches.
Public Sub DRS_FindAll_Delete()
Dim c As Range
Dim firstAddress As String
Dim WorkRng As Range
Set WorkRng = Application.Selection
Set WorkRng = Application.InputBox("Range (Column)", xTitleID, WorkRng.Address, Type:=8)
Dim x As Integer
x = xlValues > 6
For Each c In WorkRng
Set c = Cells.Find(x, LookIn:=xlValues)
If Not c Is Nothing Then
firstAddress = c.Address
Do
x.EntireRow.Delete
Set c = Cells.FindNext(c)
Loop While Not c Is Nothing
End If
Next
MsgBox ("All done!")
Clear Entire Rows
A Few Issues
If you cancel the input box, an error will occur.
What does the line x = xlValues > 6 do? If we know that xlValues = -4163 then x will be equal to a False converted to an integer i.e. x = 0. To conclude, your procedure will clear all (entire) rows whose cells in the selected column are equal to 0, if you replace x.EntireRow.Delete with c.EntireRow.Clear.
Once a cell (c) has been found and cleared, firstAddress = c.Address becomes redundant. You're not using it anyway.
A Different Approach
Whatever is selected via the input box, only the first cell is considered. It will assume that the column of the first cell contains one row of headers (row 1) and will use the cells up to the last non-empty cell. By using AutoFilter, it will filter all values greater than 6 and finally, clear the entire rows of the filtered cells.
Option Explicit
Sub DRS_FindAll_Clear()
Const Criteria As String = ">6"
Const aibPrompt As String = "Select a cell in the desired column"
Const aibTitle As String = "DRS_FindAll_Clear"
Dim aibDefault As String
If TypeOf Selection Is Range Then
aibDefault = Selection.Address
End If
Dim WorkRng As Range
On Error Resume Next
Set WorkRng = Application.InputBox( _
aibPrompt, aibTitle, aibDefault, , , , , 8)
On Error GoTo 0
If WorkRng Is Nothing Then Exit Sub
Application.ScreenUpdating = False
Dim ws As Worksheet: Set ws = WorkRng.Worksheet
If ws.FilterMode Then ws.ShowAllData
Dim strg As Range ' Table Range (has headers)
With ws.Columns(WorkRng.Column)
Dim lCell As Range: Set lCell = .Find("*", , xlFormulas, , , xlPrevious)
If lCell Is Nothing Then Exit Sub ' no data in column
Set strg = .Cells(1).Resize(lCell.Row)
End With
Dim sdrg As Range ' Data Range (no headers)
Set sdrg = strg.Resize(strg.Rows.Count - 1).Offset(1)
strg.AutoFilter 1, Criteria
Dim svdrg As Range ' Data Visible Range (no headers)
On Error Resume Next
Set svdrg = sdrg.SpecialCells(xlCellTypeVisible)
On Error GoTo 0
ws.AutoFilterMode = False
If svdrg Is Nothing Then Exit Sub
svdrg.EntireRow.Clear
Application.ScreenUpdating = True
MsgBox "All done!"
End Sub
This is the second time today this issue has come up in a SO question.
For each c in Workrng
is incorrect when you are deleting items from a collection (and yes workrng is a collection).
When you delete items from a collection in a loop you must not change the part of the collection that still has to be iterated over.
Lets say you have rows 1 to 10 and you have reached row 3 which you now delete.
When you do this, there will only be 9 rows. However, the control variable for the for each doesn't know you have deleted a row so its still counting to 10, even worse its going to skip a row, because what was row 4 is, after your deletion, now row 3. So when the control variable looks for row 4 it will actually be getting what was row 5, so the old row 4( which is now row 3) doesn't get processed at all.
Thus for collections you can only safely delete the last item in the collection. Consequently you can't use 'for each' you must use 'for i = count to 1 step -1'
I am completely new to visual basic. I have a few spreadsheets containing numbers. I want to delete any rows containing numbers outside of specific ranges. Is there a straightforward way of doing this in visual basic?
For example, in this first spreadsheet (image linked) I want to delete rows that contain cells with numbers outside of these two ranges: 60101-60501 and 74132-74532.
Can anyone give me some pointers? Thanks!
Code
You need to call it for your own needs as shown on the routine "Exec_DeleteRows". I assumed that you needed if it is equals or less to the one that you state on your routine. In this example, I will delete the rows where values are between 501-570 and then the ones between 100-200
Sub Exec_DeleteRows()
Call Exec_DeleteRowsInRangeBasedOnNumberValue(Range("C8:H11"), 501, 570)
Call Exec_DeleteRowsInRangeBasedOnNumberValue(Range("C8:H11"), 100, 200)
End Sub
Sub Exec_DeleteRowsInRangeBasedOnNumberValue(RangeToWorkIn As Range, NumPivotToDeleteRowBottom As Double, NumPivotToDeleteRowTop As Double)
Dim RangeRowsToDelete As Range
Dim ItemRange As Range
For Each ItemRange In RangeToWorkIn
If IsNumeric(ItemRange.Value) = False Then GoTo SkipStep1
If ItemRange.Value >= NumPivotToDeleteRowBottom And ItemRange.Value <= NumPivotToDeleteRowTop Then ' 1. If ItemRange.Value >= NumPivotToDeleteRowBottom And ItemRange.Value <= NumPivotToDeleteRowTop
If RangeRowsToDelete Is Nothing Then ' 2. If RangeRowsToDelete Is Nothing
Set RangeRowsToDelete = RangeToWorkIn.Parent.Rows(ItemRange.Row)
Else ' 2. If RangeRowsToDelete Is Nothing
Set RangeRowsToDelete = Union(RangeToWorkIn.Parent.Rows(ItemRange.Row), RangeRowsToDelete)
End If ' 2. If RangeRowsToDelete Is Nothing
End If ' 1. If ItemRange.Value >= NumPivotToDeleteRowBottom And ItemRange.Value <= NumPivotToDeleteRowTop
SkipStep1:
Next ItemRange
If Not (RangeRowsToDelete Is Nothing) Then RangeRowsToDelete.EntireRow.Delete
End Sub
Demo
Delete Rows Containing Wrong Numbers
It is assumed that the data starts in A1 of worksheet Sheet1 in the workbook containing this code (ThisWorkbook) and has a row of headers (2).
This is just a basic example to get familiar with variables, data types, objects, loops, and If statements. It can be improved on multiple accounts.
Option Explicit
Sub DeleteWrongRows()
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim ws As Worksheet: Set ws = wb.Worksheets("Sheet1") ' worksheet
Dim rg As Range: Set rg = ws.Range("A1").CurrentRegion ' range
Application.ScreenUpdating = False
Dim rrg As Range ' Row Range
Dim rCell As Range ' Cell in Row Range
Dim rValue As Variant ' Value in Cell
Dim r As Long ' Row
Dim DoDelete As Boolean
' Loop backwards through the rows of the range.
For r = rg.Rows.Count To 2 Step -1
Set rrg = rg.Rows(r)
' Loop through cells in row.
For Each rCell In rrg.Cells
rValue = rCell.Value
If IsNumeric(rValue) Then ' is a number
If rValue >= 60101 And rValue <= 60501 Then ' keep
ElseIf rValue >= 74132 And rValue <= 74532 Then ' keep
Else ' delete (outside the number ranges)
DoDelete = True
End If
Else ' is not a number
DoDelete = True
End If
If DoDelete Then ' found a cell containing a wrong value
rCell.EntireRow.Delete
DoDelete = False
Exit For ' no need to check any more cells
'Else ' found no cell containing a wrong value (do nothing)
End If
Next rCell
Next r
Application.ScreenUpdating = True
MsgBox "Rows with wrong numbers deleted.", vbInformation
End Sub
Using Range.Delete is the built-in way of completely erasing a row in Excel VBA. To check an entire row for numbers meeting a certain criteria, you would need a Loop and an If Statement.
To evaluate a lot of values at a faster pace, it is smart to first grab the relevant data off the Excel sheet into an Array. Once in the array, it is easy to set up the loop to run from the first element (LBound) to the final element (UBound) for each row and column of the array.
Also, when deleting a lot of Ranges from a worksheet, it is faster and less messy to first collect (Union) the ranges while you're still looping, and then do the delete as a single step at the end. This way the Range addresses aren't changing during the loop and you don't need to re-adjust in order to track their new locations. That and we can save a lot of time since the application wants to pause and recalculate the sheet after every Deletion.
All of those ideas put together:
Sub Example()
DeleteRowsOutside ThisWorkbook.Worksheets("Sheet1"), Array(60101, 60501), Array(74132, 74532)
End Sub
Sub DeleteRowsOutside(OnSheet As Worksheet, ParamArray Min_and_Max() As Variant)
If OnSheet Is Nothing Then Set OnSheet = ActiveSheet
'Find the Bottom Corner of the sheet
Dim BottomCorner As Range
Set BottomCorner = OnSheet.Cells.Find("*", After:=OnSheet.Range("A1"), SearchDirection:=xlPrevious)
If BottomCorner Is Nothing Then Exit Sub
'Grab all values into an array
Dim ValArr() As Variant
ValArr = OnSheet.Range(OnSheet.Cells(1, 1), BottomCorner).Value
'Check each row value against min & max
Dim i As Long, j As Long, DeleteRows As Range
For i = LBound(ValArr, 1) To UBound(ValArr, 1) 'For each Row
For j = LBound(ValArr, 2) To UBound(ValArr, 2) 'For each column
Dim v As Variant: v = ValArr(i, j)
If IsNumeric(v) Then
Dim BoundaryPair As Variant, Is_Within_A_Boundary As Boolean
Is_Within_A_Boundary = False 'default value
For Each BoundaryPair In Min_and_Max
If v >= BoundaryPair(0) And v <= BoundaryPair(1) Then
Is_Within_A_Boundary = True
Exit For
End If
Next BoundaryPair
If Not Is_Within_A_Boundary Then
'v is not within any acceptable ranges! Mark row for deletion
If DeleteRows Is Nothing Then
Set DeleteRows = OnSheet.Rows(i)
Else
Set DeleteRows = Union(DeleteRows, OnSheet.Rows(i))
End If
GoTo NextRow 'skip to next row
End If
End If
Next j
NextRow:
Next i
If Not DeleteRows Is Nothing Then DeleteRows.EntireRow.Delete
End Sub Exit For 'skip to next row
End If
End If
Next j
Next i
If Not DeleteRows Is Nothing Then DeleteRows.EntireRow.Delete
End Sub
I use a ParamArray to accept a variable number of Min and Max ranges. To keep things tidy, the Min and Max pairs are each in an array of their own. As long as all the numbers in the row are within any of the provided ranges, the row will not be deleted.
Here's some code with Regex and with scripting dictionary that I've been working on. I made this for my purposes, but it may be useful here and to others.
I found a way for selecting noncontinguous cells based on an array and then deleting those cells.
In this case, I selected by row number because VBA prevented deletion of rows due to overlapping ranges.
Sub findvalues()
Dim Reg_Exp, regexMatches, dict As Object
Dim anArr As Variant
Dim r As Range, rC As Range
Set r = Sheets(3).UsedRange
Set r = r.Offset(1).Resize(r.Rows.Count - 1, r.Columns.Count)
Set Reg_Exp = CreateObject("vbscript.regexp")
With Reg_Exp
.Pattern = "^[6-6]?[0-0]?[1-5]?[0-0]?[1-1]?$|^60501$" 'This pattern is for the 60101 to 60501 range.
End With
Set dict = CreateObject("Scripting.Dictionary")
For Each rC In r
If rC.Value = "" Then GoTo NextRC ''skip blanks
Set regexMatches = Reg_Exp.Execute(rC.Value)
If regexMatches.Count = 0 Then
On Error Resume Next
dict.Add rC.Row & ":" & rC.Row, 1
End If
NextRC:
Next rC
On Error GoTo 0
anArr = Join(dict.Keys, ", ")
Sheets(3).Range(anArr).Delete Shift:=xlShiftUp
End Sub
I have established, in Excel VBA, a range biased off of the location of two values in a data set. The row numbers of the start and stop in the range will change with data entry so I needed to create a range that will always offset from a set area. I now need to count the number of rows/values in the range so that once I copy the data in the range I can then remove the duplicates without altering the original list. How can I count the number of rows in my range?
I have attempted to use copyrange.Rows.Count but got error 438
Sub count_ID_List()
Set botrow = Cells.Find("Stud ID")
'Finds the first row of the count section of the invitory'
Set toprow = Cells.Find("Stud Part Number")
'Finds the top row of the company invintory'
Set copyrange = Range(toprow.Offset(1, 0).Address, botrow.Offset(-12, 1).Address)
Set copyto = Range(botrow.Offset(1, 0), botrow.Offset(1, 0))
copyrange.Copy (copyto)
'this is where i would like to then remove duplicates from the newly copied data'
End Sub
After using the Range.Find method you always need to test if something was found:
Set BotRow = Cells.Find("Stud ID")
If BotRow Is Nothing Then
MsgBox "Stud ID was not found!"
Exit Sub
End If
Always define the LookAt parameter in the find method otherwise Excel uses whatever was used before (by either a user or VBA).
Specify for all Cells and Range objects in which worksheet they are.
Use Option Explicit and declare all your variables properly.
The following should work:
Option Explicit
Public Sub count_ID_List()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1") 'define your sheet name here
'Finds the first row of the count section of the invitory'
Dim BotRow As Range
Set BotRow = ws.Cells.Find(What:="Stud ID", LookAt:=xlWhole)
If BotRow Is Nothing Then
MsgBox "'Stud ID' was not found!"
Exit Sub
End If
'Finds the top row of the company invintory'
Dim TopRow As Range
Set TopRow = ws.Cells.Find(What:="Stud Part Number", LookAt:=xlWhole)
If TopRow Is Nothing Then
MsgBox "'Stud Part Number' was not found!"
Exit Sub
End If
Dim CopyRange As Range
Set CopyRange = ws.Range(TopRow.Offset(1, 0), BotRow.Offset(-12, 1))
Dim CopyTo As Range
Set CopyTo = BotRow.Offset(1, 0)
'output row count
Debug.Print CopyRange.Rows.Count
CopyRange.Copy Destination:=CopyTo
'this is where i would like to then remove duplicates from the newly copied data'
CopyTo.Resize(RowSize:=CopyRange.Rows.Count).RemoveDuplicates Columns:=Array(1), Header:=xlNo
End Sub
I'm currently working on the statement that implies, that if any of the cell value in the range of "G3:ED3" in the worksheet named "Matrix", matches the cell value in the range of "H3:H204" in the worksheet named "Staff" and any cell value in the range "G5:ED57" in the "Matrix" worksheet is numeric, then the value of the cell in a column B, that intersects the numeric value, is retrieving to the required cell address in the target template.
Here's what I have tried so far:
Dim rng1 As Range
Set rng1 = Worksheets("Matrix").Range("G3:ED3")
Dim rng2 As Range
Set rng2 = Worksheets("Staff").Range("H3:H204")
Dim rng3 As Range
Set rng3 = Worksheets("Matrix").Range("G5:ED57")
For Each cell In Range(rng1, rng2, rng3)
While IsNumeric(rng3) And rng1.Value = rng2.Value
Worksheets("Matrix").Columns("B").Find(0).Row =
Worksheets("TEMPLATE_TARGET").Value(12, 4)
Wend
I'm unsure how to define the statement, so the code would automatically retrieve the value of the cell in a column B, that intersects any cell that contains numeric value in the rng3. Any recommendations would be highly appreciated.
it's probably best you take a proper look into documentation / whatever learning resource you are using as you seem to have missunderstood how While works (alongside few other things)
While is a loop within itself, it does not act as an Exit Condition for the For loop.
With all that said, it's also unclear from your question what you're trying to achieve.
My presumption is, that you want to check for all the conditions and
then if they do match, you're looking to paste the result into the
"TEMPLATE" sheet
First we create a function th ceck for values in the two data ranges:
Private Function IsInColumn(ByVal value As Variant, ByVal inSheet As String) As Boolean
Dim searchrange As Range
On Error Resume Next ' disables error checking (Subscript out of range if sheet not found)
' the range we search in
If Trim(LCase(inSheet)) = "matrix" Then
Set searchrange = Sheets("Matrix").Range("G5:ED7")
ElseIf Trim(LCase(inSheet)) = "staff" Then
Set searchrange = Sheets("Staff").Range("H3:H204")
Else
MsgBox ("Sheet: " & inSheet & " was not found")
Exit Function
End If
On Error GoTo 0 ' re-enable error checking
Dim result As Range
Set result = searchrange.Find(What:=value, LookIn:=xlValues, LookAt:=xlWhole)
' Find returns the find to a Range called result
If result Is Nothing Then
IsInColumn = False ' if not found is search range, return false
Else
If IsNumeric(result) Then ' check for number
IsInColumn = True ' ding ding ding, match was found
Else
IsInColumn = False ' if it's not a number
End If
End If
End Function
And then we run the procedure for our search.
Private Sub check_in_column()
Dim looprange As Range: Set looprange = Sheets("Matrix").Range("G3:ED3")
Dim last_row As Long
For Each cell In looprange ' loops through all the cells in looprange
'utlizes our created IsInColumn function
If IsInColumn(cell.Value2, "Matrix") = True And _
IsInColumn(cell.Value2, "Staff") = True Then
' finds last actively used row in TEMPLATE_TARGET
last_row = Sheets("TEMPLATE_TARGET").Cells(Rows.Count, "A").End(xlUp).Row
' pastes the found value
Sheets("TEMPLATE_TARGET").Cells(last_row, "A") = cell.Value2
End If
' otherwise go to next cell
Next cell
End Sub
I redefined your ranges a little in my example for utility reasons but it works as expected
In my Matrix sheet: (staff sheet only contains copy of this table)
In my TEMPLATE_TARGET sheet after running the procedure.
Result as expected
If I understand well, I would have done something like this:
Option Explicit
Public Sub Main()
Dim wsMatrix As Worksheet: Set wsMatrix = ThisWorkbook.Worksheets("Matrix")
Dim rgMatrix As Range: Set rgMatrix = wsMatrix.Range("G3:ED3")
Dim cell As Range
Dim cellStaff As Range
Dim cellMatrix As Range
For Each cell In rgMatrix
If CheckRangeStaff(cell.Range) And CheckRangeMatrix() Then
'Process in a column B? Which sheet? Which cell? Which Process?
End If
Next cell
Debug.Print ("End program.")
End Sub
Public Function CheckRangeStaff(ByVal value As String) As Boolean
Dim wsStaff As Worksheet: Set wsStaff = ThisWorkbook.Worksheets("Staff")
Dim rgStaff As Range: Set rgStaff = wsStaff.Range("H3:H204")
Dim res As Boolean
Dim cell As Range
res = False
For Each cell In rgStaff
If cell.value = value Then
res = True
Exit For
End If
Next cell
CheckRangeStaff = res
End Function
Public Function CheckRangeMatrix() As Boolean
Dim wsMatrix As Worksheet: Set wsMatrix = ThisWorkbook.Worksheets("Matrix")
Dim rgMatrix As Range: Set rgMatrix = wsMatrix.Range("G5:ED57")
Dim res As Boolean
Dim cell As Range
res = False
For Each cell In rgMatrix
If IsNumeric(cell.value) Then
res = True
Exit For
End If
Next cell
CheckRangeMatrix = res
End Function
so i have some code that outputs this on a spreasheet:
what i want is that you see those empty columns i need them to be gone and have all the columns beside each other to save space.
so is there a way for me to check if a column is empty and if it is i need to pretty much cut and paste the next bunch of columns onto the empty ones WITH their properties such as color code and border.
any help is much appreciated, and thnx in advance. ^_^ :D
Try WorksheetFunction.CountA(Columns( *REF* )), replacing * REF * with the reference to each column (e.g. using variable and looping through)
If this = 0, the column is empty.
You can then just delete the empty columns, e.g. using If... Then in your loop.
(Have a look at:
http://analysistabs.com/excel-vba/delete-rows-columns/ for example)
Try this:
Sub DeleteColumns()
Dim rng As Range
Dim i As Long
Dim wkSht As Worksheet
Set wkSht = ThisWorkbook.Sheets("Sheet1") '--> enter your sheet name here
Set rng = wkSht.Range("A:Z") '--> set your range here
For i = rng.Columns.Count To 1 Step -1
If Application.CountA(Columns(i).EntireColumn) = 0 Then
Columns(i).Delete
End If
Next i
End Sub
You can also delete all the empty columns together using union as:
Sub DeleteColumns()
Dim rng As Range, delRng As Range
Dim i As Long
Dim wkSht As Worksheet
Set wkSht = ThisWorkbook.Sheets("Sheet2") '--> enter your sheet name here
Set rng = wkSht.Range("A:Z") '--> set your range here
For i = 1 To rng.Columns.Count
If Application.CountA(Columns(i).EntireColumn) = 0 Then
If delRng Is Nothing Then
Set delRng = Columns(i)
Else
Set delRng = Union(delRng, Columns(i))
End If
End If
Next i
delRng.Delete '--> delete all empty columns
End Sub