I want to do some column formatting but column position is changing every time so how can i use column header instead of Column Alphabet ?
Sub Excel_Format()
Columns("J:J").Select
Selection.NumberFormat = "0"
Selection.Columns.AutoFit
End Sub
You need to start defining a Name for your column. The quickest way to do it is to select the column (Column J in this case) and enter a name in the range/cell selector on the top-left part of your Workbook. See image below:
I have named the column to "MyColumn". You can now use this as a reference in your code, like this:
Sub Excel_Format()
Dim Rng As Range
Set Rng = ActiveSheet.Range("MyColumn")
Rng.NumberFormat = "0"
Rng.Columns.AutoFit
End Sub
Even if you add or remove columns to the left of column J, the reference to MyColumn will remain correct
Please, try the next way. You can use it for any header, only adapting the used constant:
Sub Excel_Format()
Dim ws As Worksheet, RngH As Range
Const myColName As String = "ColumnX" 'your column header
Set ws = ActiveSheet 'use here your necessary sheet
Set RngH = ws.rows(1).Find(myColName)
If Not RngH Is Nothing Then
With RngH.EntireColumn
.NumberFormat = "0"
.AutoFit
End With
Else
MsgBox myColName & " could not be found in the sheet first row..."
End If
End Sub
The header should exist in the first sheet row. If not, you should adapt ws.rows(1).Find( writing the necessary row, instead of `...
Selecting, activating in such a context only consumes Excel resources, not bringing any benefit.
Related
I have a filter applied to column CK, I am able to select the next visible row from the header by using the following, which also applies a formula into that active cell.
How do I fill that formula down to the bottom, without affecting the hidden rows?
Occasionally there will be no data, so it's just applying a formula to a blank row..
range("CK1").Select
ActiveSheet.range("$A$1").AutoFilter Field:=89, Criteria1:="0"
' Add if formula to find missing carriers based on patterns
Do
ActiveCell.Offset(1, 0).Select
Loop While ActiveCell.EntireRow.Hidden = True
ActiveCell.Formula2R1C1 = _
"=IFS(AND(LEN(RC[1])=18,LEFT(RC[1],2)=""1Z""), ""UPS"", AND(LEN(RC[1])=12,ISNUMBER(RC[1])),""FedEx"",AND(LEN(RC[1])=10,ISNUMBER(RC[1])),""DHL"",AND(LEN(RC[1])=11,LEFT(RC[1],2)=""06""),
It would be great if you could refrain from selecting cells or activating sheets or workbooks like you do. The only time it is fine to have Excel change its selection on screen with VBA is if you want it to.
For your problem, a simple loop will do. Example with CK1 and all the cells below it:
Dim topCell As Range, bottomCell As Range
Set topCell = Range("CK1")
Set bottomCell = topCell.end(xlDown)
'Next test is optional, although recommended (is there no cell filled under CK1?)
If bottomCell.Row >= 1048576 Then 'Current maximal row; you may change the threshold if desired.
Exit Sub
'Alternatively: Exit Function
'Other alternative example: Set bottomCell = Range("CK1000")
End If
Dim c As Range
For Each c In Range(topCell, bottomCell)
If Not c.EntireRow.Hidden Then
c.Formula2R1C1 = "" '<place your formula here>
End If
Next c
I want to return the value of the cell it's found in VBA and clear all of it's content with another 3 rows below it as well, but I'm currently stuck. I can find where the cell is coming from, but it's deleting the whole range instead of the specific range (I'm aware the range("A7:H20") was wrong). How do I select the correct range?
Sub Find_and_remove()
For Each cell In Range("A7:H20")
If cell.Value = Range("Q5") Then
'return the range of that cell and deleted it with 3 row below it'
Range("A7:H20").Clear
End If
Next cell
End Sub
Sub Find_and_remove()
Dim rng As Range
For Each rng In Range("A7:H20")
If rng.Value = Range("Q5") Then Range(rng, rng.Offset(3, 0)).Clear
Next cell
End Sub
Another solution:
I am using a sub to which you pass the parameters:
value to be found
range where to look in and clear contents
number of rows below the found value to be cleared.
Furthermore I am looking from the bottom to the top of the range - otherwise cells could be cleared that contain the string to be found - and then below values won't get cleared:
Option Explicit
'>>> example of how to call the findAndRemove-Sub <<<
Public Sub test_FindAndRemove()
With ActiveSheet ' adjust this to your needs
findAndRemove .Range("Q5"), .Range("A7:H20"), 3
End With
End Sub
'>>>> this is the sub that is doing the work <<<<<
Public Sub findAndRemove(strFind As String, _
rgLookup As Range, _
cntDeleteRowsBelow As Long)
Dim i As Long, c As Range
'start from the bottom and go up
'otherwise you could delete further strFind-cells unintentionally
For i = rgLookup.Rows.Count To 1 Step -1
For Each c In rgLookup.Rows(i).Cells
If c.Value = strFind Then
'ATTENTION:
'at this point there is no check if below row contains the strFind-value!
c.Resize(cntDeleteRowsBelow + 1).Clear
End If
Next
Next
End Sub
You could just use cell.Clear, or if you want the cell cleared and the next 3 below it use something like this
For i = 0 To 3
cell.Offset(i, 0).Clear
Next
I think you mean "return the address of that cell", no? Debug.Print(cell.Address) will get you this info. But you don't actually need it here. Instead of Range("A7:H20").Clear write cell.Resize(1 + i, 1).Clear with i = number of rows you want to clear along with cell itself (no need for a loop).
I'm trying to find a column with a string of text and copy it into another sheet. The top row would contain text "Module Check" but might have other text after or before. I know that I can do the following if I know the exact string. How do I search for a string in the top row and then select the whole column based on that string?
Sub FinalAssignmentImportedtoCleaned()
Sheets("Imported").Select
Set MR = Range("A1:ZZ1")
For Each Cell In MR
If Cell.Value = "Module Check" Then Cell.EntireColumn.Copy
Next
Sheets("Cleaned").Select
Range("D:D").Select
ActiveSheet.Paste
[D1].Value = "Module Check"
End Sub
The Like operator will match pattern of a string against the full string. That's useful when you want to use wildcard in your match.
So change = with Like and this code If Cell.Value Like "*Module Check*" Then Cell.EntireColumn.Copy should do the trick.
If you want to check if only word exist in the end of the sentence you can do "*Module Check"
If you want to avoid case-sensitivity you can use LCase$(), i.e.
If LCase$(Cell.Value) Like LCase$("*Module Check*") Then Cell.EntireColumn.Copy
If you want to avoid select and make code more robust you could rewrite it a little bit:
Sub FinalAssignmentImportedtoCleaned()
Dim lcol As Long
Dim ws_copy As Worksheet 'Declare sheet to copy from
Dim ws_paste As Worksheet 'Declare sheet to paste to
Set ws_copy = ActiveWorkbook.Worksheets("Imported") 'Set sheet name to copy from
Set ws_paste = ActiveWorkbook.Worksheets("Cleaned") 'Set sheet name to paste to
lcol = ws_copy.Cells(1, Columns.Count).End(xlToLeft).Column 'Find last column with data at row 1
Set MR = ws_copy.Range(ws_copy.Cells(1, "A"), ws_copy.Cells(1, lcol))
For Each Cell In MR
If Cell.Value Like "*Module Check*" Then Cell.EntireColumn.Copy
Next
ws_paste.Range("D1").PasteSpecial
ws_paste.Cells(1, "D").Value = "Module Check"
End Sub
Is it possible to write a vba macro that determines if there are any empty cells in a given range and returns the row number of that cell?
I'm new to vba and all that I managed to write after searching the internet was something that takes a range and colors every emty cell in it red:
Sub EmptyRed()
If TypeName(Selection) <> "Range" Then Exit Sub
For Each cell In Selection
If IsEmpty(cell.Value) Then cell.Interior.Color = RGB(255, 0, 0)
Next cell
End Sub
The macro does basically what I want, but instead of coloring the empty cell red I would like to know the row index of the empty cell.
A little background info: I have a very large file (about 80 000 rows) that contains many merged cells. I want to import it into R with readxl. Readxl splits merged cells, puts the value in the first split cell and NA into all others. But a completely empty cell would also be assigned NA, so I thought the best thing would be to find out which cells are empty with Excel, so that I know which NA indicate a merged cell or an empty cell. Any suggestions on how to solve this problem are very welcome, thanks!
Edit: To clarify: Ideally, I want to unmerge all cells in my document and fill each split cell with the content of the previously merged cell. But I found macros on the web that are supposed to do exactly that, but they didn't work on my file, so I thought I could just determine blank cells and then work on them in R. I usually don't work with Excel so I know very little about it, so sorry if my thought process is far too complicated.
To do exactly what you state in your title:
If IsEmpty(cell.Value) Then Debug.Print cell.Row
But there are also Excel methods to determine merged cells and act on them. So And I'm not sure exactly what you want to do with the information.
EDIT
Adding on what you say you want to do with the results, perhaps this VBA code might help:
Option Explicit
Sub EmptyRed()
Dim myMergedRange As Range, myCell As Range, myMergedCell As Range
Dim rngProcess As Range
With Application
.ScreenUpdating = False
.Calculation = xlCalculationManual
.EnableEvents = False
End With
Set rngProcess = Range("A1:B10")
For Each myCell In rngProcess
If myCell.MergeCells = True Then
Set myMergedRange = myCell.MergeArea
With myMergedRange
.MergeCells = False
.Value = myCell(1, 1)
End With
End If
Next myCell
With Application
.ScreenUpdating = True
.Calculation = xlCalculationAutomatic
.EnableEvents = True
End With
End sub
Note that I explicitly declare all variables, and I hard coded the range to check. There are various ways of declaring the range to be checked; using 'Selection' is usually rarely preferred.
Before anything else: From the opposite end of the spectrum, you can use Range.MergeCells or Range.MergeArea to determine if a Cell is part of a Merged Area. But, I digress...
You can use Cell.Row to get the row number. How you return or display that is up to you - could be a Message Box, a delimited string, or an array, or even a multi-area range.
A Sub cannot return anything once called, so you may want a Function instead, e.g. Public Function EmptyRed() As String
(Also, I would recommend you get in the habit of explicitly declaring all of your variables, and perhaps using Option Explicit too, before you run into a typo-based error. Just add Dim cell As Range at the top of the sub for now)
Sub FF()
Dim r, wksOutput As Worksheet
Dim cell As Range, rng As Range, rngArea As Range
With Selection
.UnMerge
'// Get only blank cells
Set rng = .SpecialCells(xlCellTypeBlanks)
'// Make blank cells red
rng.Interior.Color = vbRed
End With
'// Create output worksheet
Set wksOutput = Sheets.Add()
With wksOutput
For Each rngArea In rng.Areas
For Each cell In rngArea
r = r + 1
'// Write down the row of blank cell
.Cells(r, 1) = cell.Row
Next
Next
'// Remove duplicates
.Range("A:A").RemoveDuplicates Array(1), xlNo
End With
End Sub
There are a couple ways:
Sub EmptyRed()
Dim rgn,targetrgn as range
Dim ads as string ‘ return rgn address
Set targetrgn= ‘ your selection
For Each rgn In Targetrgn
If IsEmpty(rgn.Value) Then
‘1. Use address function, and from there you can stripe out the column and row
Ads=application.worksheetfunction.addres(cell,1)’ the second input control the address format, w/o $
‘2. Range.row & range.column
Ads=“row:” & rgn.row & “, col: “ & rgn.column
End if
Next rgn
End Sub
Ps: I edited the code on my phone and will debug further when I have a computer. And I am just more used to use “range” rather than “cell”.
To clarify: Ideally, I want to unmerge all cells in my document and fill each split cell with the content of the previously merged cell.
Cycle through all cells in the worksheet's UsedRange
If merged, unmerge and fill the unmerged area with the value from the formerly merged area.
If not merged but blank, collect for address output.
Sub fillMerged()
Dim r As Range, br As Range, mr As Range
For Each r In ActiveSheet.UsedRange
If r.Address <> r.MergeArea.Address Then
'merged cells - unmerge and set value to all
Set mr = r.MergeArea
r.UnMerge
mr.Value = mr.Cells(1).Value
ElseIf IsEmpty(r) Then
'unmerged blank cell
If br Is Nothing Then
Set br = r
Else
Set br = Union(br, r)
End If
End If
Next r
Debug.Print "blank cells: " & br.Address(0, 0)
End Sub
I have the example where I want to write a VBA statement which will select all data in a single column, there are no blanks in the column data. The column position will never change e.g. column A, and the data starts in row 3. However the total number of rows in the column will change regularly.
I want the system to dynamically select all the cells in column and then I can run a method against these selected pieces of data.
As an example of performing an action on your range without selecting it:
Public Sub Test()
Dim rColA As Range
With ThisWorkbook.Worksheets("Sheet1")
Set rColA = .Range(.Cells(3, 1), .Cells(.Rows.Count, 1).End(xlUp))
MsgBox "Column A range is " & rColA.Address 'Delete if you want.
rColA.Interior.Color = RGB(255, 0, 0) 'Turn the back colour red.
rColA.Cells(2, 1).Insert Shift:=xlDown 'Insert a blank row at second cell in range
'So will insert at A4.
'If the first cell in your range is a number then double it.
If IsNumeric(rColA.Cells(1, 1)) Then
rColA.Cells(1, 1) = rColA.Cells(1, 1) * 2
End If
End With
End Sub
Try
Dim LastRow as Long, sht as worksheet
Set sht = ThisWorkbook.Worksheets("My Sheet Name")
LastRow = sht.Cells(sht.Rows.Count, 1).End(xlUp).Row
sht.Range("A3:A" & LastRow).Select
Like Darren Bartrup-Cook says, you may not need to select the data, you can almost always perform actions directly which is much faster.
If your column is "isolated" meaning no other nonblank cells touch your data you can use:
Range("firstCellInYourColumn").CurrentRegion.Select
(this works the same way as Ctrl+* from keyboard)
otherwise use:
Range(Range("firstCellInYourColumn"), Range("firstCellInYourColumn").End(xlDown)).Select
both will work if there are really no blanks within your data.
You should also prepend all Range with worksheet expression, I omitted this.