I have a lot of Cells in my book that don't have any value but still count toward the "Count". When i try to navigate with Ctrl and arrow keys these cells also "interrupt" the scrolling, which is quite annoying. When i select these cells and delete them they don't have a "value" anymore (also works if I edit the text and press Enter on each one), but it's a decently sized document with quite a lot of these. I wonder what is the cause and if there's a way to fix it.
"Count: 14" in empty cells:
The UsedRange property of a worksheet also includes the cells with ghost data that you are seeing which can help you dynamically clear the right cells. Note this will clear everything from the blank cells. That includes comments, formatting, etc so just make sure that isn't a problem for other cells that don't have the ghost data problem.
Loop through each cell in the UsedRange and look for cells with Len = 0 and HasFormula = False i.e. your blanks to be cleared
Add these cells (no characters) to a Union (collection of cells)
Once the loop is complete, clear the Union which will hopefully resolve your issue
Sub Clear()
Dim Target As Range
Dim ClearMe As Range
For Each Target In Sheets("Sheet1").UsedRange
If Len(Target) = 0 And Not Target.HasFormula Then
If Not ClearMe Is Nothing Then
Set ClearMe = Union(ClearMe, Target)
Else
Set ClearMe = Target
End If
End If
Next Target
If Not ClearMe Is Nothing Then ClearMe.Clear
End Sub
If you want to test this before running the macro on your entire sheet then replace the UsedRange with the actual range you showed us in your photo. For instance, For Each Target In Sheets("Sheet1").Range("A1:A10") (idk the actual range). Once the macro is done, see if that same range shows you a count once it's highlighted
If cell A2 appears to be empty, and A2 has zero length, in another cell enter:
=IF(LEN(A2)<>0,"stuff",IF(COUNTA(A2)=0,"genuine empty","null character"))
This will allow you to distinguish:
characters in the cell
nothing at all in the cell
a formula returning Null in the cell or a Null constant (by Null I mean a zero length string)
If you want to Clear these cells, run this short macro:
Sub diogo()
Dim cell As Range, wf As WorksheetFunction
Set wf = Application.WorksheetFunction
For Each cell In ActiveSheet.UsedRange
If Len(cell.Value) = 0 Then
If wf.CountA(cell) = 1 Then
cell.Clear
End If
End If
Next cell
End Sub
Related
Quick question, new to VBA, how do you change cell data in a certain range according to data filter in other range?
For the Code as follows I want to first identify if values from E11 to G13 are 0. If they are, I want to change the corresponding cells in Range O9 to Q11 to 0 as well. If the values from E11 to G13 are not 0, keep the original values in range O9 to Q11.
Need help. Thanks!
Sub If_loop2()
For Each Cell In Range("O9:Q11")
If Range("E11:G13").Value = 0 Then
Cell.Value = 0
Else
Cell.Value = Cell.Value
End If
Next Cell
End Sub
I'm sure there are many ways to solve this, but since each cell is referenced another cell at a specific offset from it (2 rows up and 10 rows to the left), we can use Offset to check the relevant cell and do the needful:
Sub If_loop2()
For Each c In Range("O9:Q11")
If c.Offset(2, -10) = 0 Then
c.Value = 0
End If
Next c
End Sub
Without using Offset, we can loop over one of the ranges in order using a cells property of the range (it will loop from left to right, like reading a book). Then compare to the cell in the other range, with the same index:
Sub If_loop3()
Dim r1 As Range
Dim r2 As Range
Set r1 = Range("O9:Q11")
Set r2 = Range("E11:G13")
For i = 1 To r1.Count
If r2.Cells(i) = 0 Then
r1.Cells(i) = 0
End If
Next i
End Sub
P.S. a non-VBA solution
It can often be preferable to use a non-VBA solution, as non-VBA solutions are easy to understand and maintain. So to that end, simply create a third range with some standard IF() formulas.
For example, in cell O13 use the formula =IF(E11=0,0,O9) and copy this formula across two more cells and down two cells. The output will also agree with the desired results (i.e., if E11 is zero, return 0, otherwise return the value of O9). Now you can work in the ranges E11:G13 and O9:Q11 as much as you want, and the "output" range in O13:Q15 will keep track of these comparisons.
I have an excel sheet with numbers in each cell. I want to eliminate the cells containing values which are larger than a specific value, different for each row, for example in the picture
I want to eliminate all the cells in a certain row that has values more than the BL cell.
Not sure the exact context in which this is being used, So possibly some conditional formatting would be more stable?
Also not sure what you meant by "Eliminate" so the following code just turns the cell red.
anyway, hopefully this code will help you get started :)
Sub Cell_Vaue_Check()
Dim row As Excel.Range
Dim cel As Excel.Range
For Each row In Sheets("Sheet1").Range("A1:C5").Rows '<<- Replace "Sheets("Sheet1").Range("A1:C5")" with the Sheet and Range you want to check
For Each cel In row.Cells
If cel.Value > Range("E" & cel.row).Value Then '<<- Replace "E" with the Column in which the check value is located
cel.Interior.Color = RGB(288, 0, 0) '<<- This line turns the cell Red. Replace it with whatever code you want depending on what "eliminate" means to you
End If
Next
Next
Set row = Nothing
Set cel = Nothing
End Sub
If Anybody has any improvements please feel free to Add!
IMPORTANT EDIT: The main issue here is caused by hidden merged cells that are causing the entirity of their active range to be selected. Unless you know a way how to dynamically skip merged cells (in a dynamic range), the it most likely won't help. Have changed the entirity of question accordingly
any idea what am I doing wrong?
Got the following code, fyi the function find_last_row returns the value of last active row as integer. In this case, the returned variable would be 40
Private Sub initalize_button_Click()
Dim lastRow As Integer
Dim ws As Worksheet: Set ws = Sheets("Training_Planner")
lastRow = find_last_row
With ws
.Activate
.Range("E5:H" & lastRow).Select
End With
End Sub
Pretty basic code, should open the worksheet Training_Planner and select from E5 to HlastRow (in this case lastRow is 40) so the selected range should be E5:H40
Here is the expected result:
What I get instead:
Curiously enough, it selects only active range, but it's as if it didn't pay attention to columns, instead of the expected E5:H40 i get B5:I40
Any idea what's causing this?
Ok, first of all, if your range is gonna start always as E5, your range is 50% dinamic, because it starts always in same column and same row. Your Range is (Cells(a,b),Cells(c,d)), this means a = 5 and b = 5 (Column E).
Also, you say and Inputbox asks users for end cell of range (in your example is H40, but this is dynamic).
So, my code checks EVERY SINGLE cell in the range formed, and then, using Application.UnionI set a final big range. We cannot just use an array to select all of them, because your range is dynamic, and selecting ranges with arrays is limited to 30 args, so we need to update our FinalRange for each cell.
Dim MyCell As Range
Dim RangeWanted As Range
Dim MyFinalRange As Range
Set RangeWanted = Range("E5:" & InputBox("Cell Address")) 'User inputs Final Cell of Range. Start is always E5
'let's get all invididual addresses of each cell inthat dynamic RangeWanted
For Each MyCell In RangeWanted
If MyCell.MergeCells = False Then 'If not merged, we add it to FinalRange
If MyFinalRange Is Nothing Then
Set MyFinalRange = MyCell
Else
Set MyFinalRange = Application.Union(MyFinalRange, MyCell)
End If
End If
Next MyCell
Set RangeWanted = Nothing
MyFinalRange.Select
With this code, from Range("E5:H40") in image,yellow cells are merged. I want to select only the not merged ones. And using this code, I get this:
My example is with Range("E5:H40") but it works also with other ranges.
Try it and adapt the code to your needs.
Whenever something small like this is happening, simply try to simplify as much as you can. In your case, it would be this:
Sub TestMe()
Worksheets("Training_Planner").Range("E5:H40").Select
End Sub
If it selects E5:H40 then everything is ok. If not, try to select it manually. Probably you have a hidden row, which is merged from B to I, thus it is happenning this way.
Instead of this:
.Range("E5:H" & lastRow).Select
Try going with this:
.Range("E5", (Cells(Rows.Count, "H").End(xlUp))).Select
It count all the rows "H" has and then goes up until it finds the first item. And it will then select from "E1" to last item in "H"
I have a spreadsheet with a large amount of data in. About half the cells are merged horizontally with other cells and contain names e.g. John Doe.
Does anyone know how to write a macro to unmerge the cells while distributing the value of the cell to all the cells that were previously merged?
Cheers
Jack
EDIT: The reason I am doing this is to check to see if two adjacent cells are equal i.e. is A1 = A2. But I run into problems when either cell is merged. If anyone knows a way around this problem without separating the cells and copying the data that would be even better!
The idea I provide below is tested for Excel 2010 VBA Win7. However, being not sure I hope it should work as for Mac, too (as this is rather set of standard properties and methods of Range object). If this doesn't work please let me know to delete my answer.
This simple code will work for selected area however it's quite easy to change it to any other range. Some other comment inside the code below.
Sub Unmerging_Selection()
Dim tmpAddress As String
Dim Cell As Range
'change Selection below for any other range to process
For Each Cell In Selection
'check if cell is merged
If Cell.MergeCells Then
'if so- check the range merged
tmpAddress = Cell.MergeArea.Address
'umnerge
Cell.UnMerge
'put the value of the cell to
Range(tmpAddress) = Cell
End If
Next
End sub
And the picture presenting before and after result:
I was able to get the solution from KazJaw to work on a mac with one edit, changing Cell.UnMerge to
ActiveSheet.UsedRange.MergeCells = False, as provided by Ron Debruin here: http://www.rondebruin.nl/mac/mac027.htm.
Sub Unmerging_Selection()
Dim tmpAddress As String
Dim Cell As Range
'change Selection below for any other range to process
For Each Cell In Selection
'check if cell is merged
If Cell.MergeCells Then
'if so- check the range merged
tmpAddress = Cell.MergeArea.Address
'umnerge
ActiveSheet.UsedRange.MergeCells = False
'put the value of the cell to
Range(tmpAddress) = Cell
End If
Next
End sub
I'm trying to create a simple macro that copys the two first numbers in each cell in a column and printing them in a different column. This is in a excel-document with more than 1 worksheet. I've tried for a while to write the code, but with no prior experience, I have a hard time figuring out what to do. I know the "left()"-function is able to do this, but I don't know how I define which column to draw data from and to which column it will be printed. Any help will be greatly appreciated.
With no prior experience to writing VBA code, I am going to reccommend you stick to the formula method of doing. Honestly, even if you were familiar with VBA, you might still opt to use the formula.
A formula is put into the actual cell you want the value to be copied.
=LEFT(sourceCell, #of characters you want)
This is how it would look:
=LEFT(Sheet1!A1, 2)
Think of it as saying "this cell shall equal the first n characters in cell OO, starting from the left".
Once you are done with your formula, if you don't need it to be binded to the source anymore (if the sourceCell changes, so does the cell with the LEFT formula), you can highlight the cells, Ctrl + C to copy, then right-click and select Paste Special. Then select VALUE and hit OK and now the cells are hard-coded with the value they were showing, as if you typed it yourself.
Once you master using formulas, the next step is VBA. Don't go confusing yourself by jumping into VBA and writing code for ranges, etc. if you aren't comfortable with using =LEFT yet. One step at a time, and you'll be a pro before you know it. :)
Here is a quick sample sub to get you started:
Public Sub LeftSub()
Dim SourceRange As Range, DestinationRange As Range, i As Integer
'Define our source range as A1:A10 of Sheet1
Set SourceRange = Sheet1.Range("A1:A10")
'Define our target range where we will print.
'Note that this is expected to be of same shape as source
Set DestinationRange = Sheet1.Range("B1:B10")
'Iterate through each source cell and print left 2 bits in target cell
For i = 1 To SourceRange.Count
DestinationRange(i, 1).Value = Left(SourceRange(i, 1).Value, 2)
Next i
End Sub
How about
Sub foo()
Dim cell As Range
Dim sourceRange As Range
'//define the source column - looks for contiguous downward data from A1;
Set sourceRange = Range(Sheets("Sheet1").Range("A1"), Selection.End(xlDown))
'//iterate each cell
For Each cell In sourceRange
If IsEmpty(cell.Value) Then Exit For
'//example to place the value in corresponding row of column B in sheet 2
Sheets("Sheet2").Range("B" & cell.Row).Value = Left$(cell.Value,2)
Next
End Sub
Or an equivalent formula (in the destination cell)
=LEFT(Sheet1!A1,2)