How to work with data on multiple selection within a filter being applied? - excel

I had to rework the code a bit as I got the Error1004: pastespecial method of worksheet class failed I just specified the range for PasteSpecial xlPasteValues see the code:
Sub AvoidingSelect()
Dim rng As Range, cll As Range Set rng = Range("G2:G12854")
Sheets("Data").Range("G2:G12854").SpecialCells(xlCellTypeVisible).Copy Sheets("Data").Range("G2:G12854").PasteSpecial xlPasteValues
Application.CutCopyMode = False
For Each cll In rng
If IsNumeric(cll.Value) Then Range("G2:G12854") = Application.WorksheetFunction.RoundDown(cll.Value, 8) End If
Next End Sub
However, the last part is not working. It picks the first cell.value in the row and copy it into each cell all the way down so the value of cell H1084 is in every cell now.

Reminder, What is Rounddown's syntax? From the Microsoft Excel documentation:
ROUNDDOWN(number, num_digits)
Number – Required. Any real number that you want rounded down.
Num_digits – Required. The number of digits to which you want to round number.
So in your code the first mistake I saw is here :
Selection.WorksheetFunction.RoundDown (Activecell.Value)
This line must be like below :
Application.WorksheetFunction.RoundDown (Activecell.Value , 0)
So your code would be like that :
Sub Macro1()
Dim Activecell As Range
Dim rounddownvar As Double
Selection.SpecialCells(xlCellTypeVisible).Select
For Each Activecell In Selection
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues
rounddownvar = Application.WorksheetFunction.rounddown(Activecell.Value, 1)
Debug.Print rounddownvar
Next Activecell
End Sub
I added Application.WorksheetFunction.rounddown(Activecell.Value, 1) into a var because this line returns a number ...
Without select to be more efficient :
Sub AvoidingSelect()
Dim rng As Range, cll As Range
Set rng = Range(Range("A2:B2"), Range("A2:B2").End(xlDown)).SpecialCells(xlCellTypeVisible)
Sheets("Sheet1").Range("A1:AA100000").SpecialCells(xlCellTypeVisible).Copy
Sheets("Sheet1").PasteSpecial xlPasteValues
For Each cll In rng
If IsNumeric(cll.Value) Then
Debug.Print Application.WorksheetFunction.RoundDown(cll.Value, 0)
End If
Next
End Sub
CAUTION:
Please respect RoundDown syntax :
RoundDown(cll.Value, 0) here 0 is the number of digit you want to delete after the , .
For Example :
RoundDown(cll.Value, 0) give : 0.000
RoundDown(cll.Value, 3) give : 0
Working :
Sub AvoidingSelect()
Dim rng As Range, cll As Range
Set rng = Range(Range("G2:G12854"), Range("G2:G12854").End(xlDown)).SpecialCells(xlCellTypeVisible)
Sheets("Sheet1").Range("G2:G12854").SpecialCells(xlCellTypeVisible).Copy
Sheets("Sheet1").Range("G2:G12854").PasteSpecial xlPasteValues
For Each cll In rng
If IsNumeric(cll.Value) Then
Debug.Print cll.Value
cll = Application.WorksheetFunction.RoundDown(cll.Value, 8)
End If
Next
End Sub

Related

How to divide every cell in a column by a constant in VBA?

I am processing a data set that has about 50 columns, and the same columns are always off by a factor of ten. So, I just want to hardcode the specific columns (starting with F here) and divide every cell in the column by 10. Right now I am getting a "Type Mismatch" error. The code is below:
Sub FixData()
Dim finalRow As Long
Dim rng As Range
Dim cell As Range
finalRow = Range("A100000").End(xlUp).Row
Set rng = Range("F1:F" & finalRow)
For Each cell In rng
cell.Value = cell.Value / 10
Next cell
End Sub
why loop when you can simply paste special and divide.
errors within the cells are ignored.
in vba, here is the code
Range("G10").Copy
Range("B2:E8").PasteSpecial Paste:=xlPasteValues, Operation:=xlDivide
Application.CutCopyMode = False
test if cell is an error and then test if it is a number prior to dividing:
Sub FixData()
Dim finalRow As Long
Dim rng As Range
Dim cell As Range
finalRow = Range("A100000").End(xlUp).Row
Set rng = Range("F1:F" & finalRow)
For Each cell In rng
If Not IsError(Cell) Then
If IsNumeric(cell) and cell <> "" Then
cell.Value = cDbl(cell.Value) / 10
End If
End If
Next cell
End Sub

VBA macro delete cells containing #N/A and shift up the cells (not the rows)

I'm creating a ranking and I need to delete all the cells with #N/A (pasted as text, not formula) and to delete those cells and shhift them up.
The worksheet contains 503 raws and I need it from column A to T.
Thanks in advance, I have tried so many VBA codes of this web and I'm not able to find something that works.
Try,
dim rng as range
with worksheets("sheet1")
on error resume next
set rng = .range("A:T").specialcells(xlcelltypeformulas, xlerrors)
if not rng is nothing then
rng.delete shift:=xlup
end if
set rng = .range("A:T").specialcells(xlcelltypeconstants, xlerrors)
if not rng is nothing then
rng.delete shift:=xlup
end if
on error goto 0
end with
This should work. There are faster ways of doing what you ask, but since you don't have that big of a data set, I just modified some code I had available.
Sub KillPoundNa()
Dim rCell As Range, WS As Worksheet, KillRng As Range, UndesireableText As String
UndesireableText = "#N/A"
Set WS = ActiveSheet
Set KillRng = WS.Cells(Rows.Count, 1)
For Each rCell In WS.UsedRange.Cells
If InStr(1, rCell.Text, UndesireableText, vbTextCompare) > 0 Then
Set KillRng = Union(KillRng, rCell)
End If
Next rCell
KillRng.Delete (xlUp)
End Sub

Run-time error : 1004 (Copying to another sheet)

I'm trying to create a VBA Macro that would search for a non-blank cell in "Sheet1" and if non-blank, it would paste the respective active cell column from "Sheet1" to the same column in "Sheet2".
Below is my code, but I'm sure I'm doing something wrong, because the code is throwing me an error : 1004.
Sub Test()
Dim cel As Range
Dim strAddress As String
Dim StartPoint As Range
Set StartPoint = ActiveCell
'Change to necessary amount of Rows & Columns
With Sheets("Sheet1").Range(Cells(9, 5), Cells(1000, 200))
Set cel = .Find(What:="*", After:=Cells(1000, 200), SearchOrder:=xlByRows, SearchDirection:=xlNext)
If Not cel Is Nothing Then
strAddress = cel.Address
Do
' Do something with cel, e.g.
StartPoint.EntireColumn.Copy Destination:=Worksheets("Sheet2").Range(StartPoint.Column & "1").End(xlToRight).Offset(1)
Set cel = .FindNext(After:=cel)
If cel Is Nothing Then Exit Do
Loop Until cel.Address = strAddress
End If
End With
End Sub
Can someone kindly advise what I'm doing wrong?
Thank you!
Try these two modifications:
With Sheets("Sheet1").Range("E9:GR1000")
.
cel.EntireColumn.Copy Worksheets("Sheet2").Columns(cel.Column)

In range find this and do that

Have a range of cell with column headings as weeks In the range of cells I want to look for a number, say
1 if it finds a 1 then look at a column in said row for a variable, 2 or 4 whatever Now I want to put a triangle (can be copy and paste a cell) in the cell that has the "1" in it then skip over the number of week variable and add another triangle and keep doing this until the end of the range. Then skip down to the next row and do the same, until the end of the range.
Then change to the next page and do the same thing... through the whole workbook.
I think I have it done, don't know if it's the best way.
I get a error 91 at the end of the second loop, the first time the second loop ends it goes through the error code.
The second time the second loop ends it errors.
I don't understand it runs through once, but not twice.
Sub Add_Triangles2()
Dim Rng As Range
Dim OffNumber As Integer
Dim SetRange As Range
Dim OffsetRange As Range
Dim ws As Worksheet
Set SetRange = Sheets("Sheet1").Range("G25") ' Used to stop the second loop in range
Worksheets(1).Activate
Worksheets(1).Range("A1").Select ' Has item to be pasted (a triangle)
Selection.Copy
For Each ws In Worksheets
Worksheets(ws.Name).Activate
With Range("C4:G25")
Set Rng = .Find(1, LookIn:=xlValues)
If Not Rng Is Nothing Then
FirstAddress = Rng.Address
Do
Rng.Activate
ActiveSheet.Paste
Do
OffNumber = Range("A" & ActiveCell.Row)
Set OffsetRange = SetRange.Offset(0, -OffNumber)
If Not ActiveCell.Address < OffsetRange.Address Then
Exit Do
Else
End If
ActiveCell.Offset(, OffNumber).Select
ActiveSheet.Paste
Loop While (ActiveCell.Address <= OffsetRange.Address)
On Error GoTo ErrorLine
Set Rng = .FindNext(Rng)
Loop While Not Rng Is Nothing And Rng.Address <> FirstAddress
End If
End With
ErrorLine:
On Error GoTo 0
Application.EnableEvents = True
Next ws
Application.CutCopyMode = False
End Sub
I was not able to get an Error 91 using the data set I built from your explanation, maybe a screenshot of the layout could help recreate the issue.
However, I would do something like this, it will look at the value of each cell in the range C4:G25, and if it equals 1, it will paste the symbol stored in Cell A1.
Sub Add_Triangles2()
Dim Rng As Range
Dim rngSymbol As Range
Dim intFindNum As Integer
Dim ws As Worksheet
Set rngSymbol = Range("A1") 'Set range variable to hold address of symbol to be pasted
intFindNum = 1 'Used to hold number to find
Worksheets(1).Activate
For Each ws In Worksheets
Worksheets(ws.Name).Activate
For Each Rng In Range("C4:G25")
If Rng.Value = intFindNum Then
rngSymbol.Copy Rng
End If
Next Rng
Next ws
End Sub
I got it....
Sub Add_TriWorking()
Dim Rng As Range
Dim rngSymbol As Range
Dim intFindNum As Integer
Dim ws As Worksheet
Dim OffNumber As Integer
Dim SetRange As Range
Dim OffsetRange As Range
Set SetRange = Sheets("Sheet1").Range("G25") ' Used to stop the second loop in range
Set rngSymbol = Range("A1") 'Set range variable to hold address of symbol to be pasted
intFindNum = 1 'Used to hold number to find
Worksheets(1).Activate
For Each ws In Worksheets
Worksheets(ws.Name).Activate
For Each Rng In Range("C4:G25")
If Rng.Value = intFindNum Then
rngSymbol.Copy Rng
Rng.Activate
ActiveCell.Copy
Do
OffNumber = Range("A" & ActiveCell.Row)
Set OffsetRange = SetRange.Offset(0, -OffNumber)
If Not ActiveCell.Address < OffsetRange.Address Then
Exit Do
Else
End If
ActiveCell.Offset(, OffNumber).Select
ActiveSheet.Paste
Loop While (ActiveCell.Address <= OffsetRange.Address)
On Error GoTo ErrorLine
End If
Next Rng
ErrorLine:
On Error GoTo 0
Application.EnableEvents = True
Next ws
Application.CutCopyMode = False
End Sub

Remove empty rows

I have an Excel macro that removes all the empty rows in an Excel sheet. This macro takes too long to finish. The files are generated automatically and every file needs to run this macro. The macro deletes one row at a time after checking its value.
I need something like this:
If rowValue = "" then
deleteThisRow And deleteAll Subsequent rows at once
End If
This is the code I am using now:
Sub RemoveRows()
Range("A8").Select
Dim checkval
Dim RowAmount
RowAmount = 93
Do
checkval = ActiveCell.Value
If (checkval = "") Then
ActiveCell.EntireRow.Delete
Else
ActiveCell.Offset(1, 0).Select
End If
RowAmount = RowAmount - 1
Loop While RowAmount > 0
End Sub
Your idea to delete all necassary rows in one operation is bang on. In addition avoiding Select and avoiding looping over a range of cells will speed thing up too.
Here's an approach that should work for you
Sub Demo()
Dim sh As Worksheet
Dim rng As Range
Dim rngBlanks As Range
' Get a reference to the sheet you want to process
Set sh = ActiveSheet
' Get a reference to the range of cells to test
With sh
Set rng = .Range(.Cells(8, 1), .Cells(.Rows.Count, 1).End(xlUp))
End With
' if there are no blanks SpecialCells will error, so handle it
On Error Resume Next
' Reduce rng to reference only blank cells
Set rngBlanks = rng.SpecialCells(xlCellTypeBlanks)
On Error GoTo 0
' see if there are any blanks
If Not rngBlanks Is Nothing Then
' delete all of them
rngBlanks.EntireRow.Delete
End If
End Sub
Update based on additional info provided: "blank" cells may contain formulas returning an empty string.
Here's an approach using AutoFilter
Sub Demo()
Dim sh As Worksheet
Dim rng As Range
Dim rngBlanks As Range
Application.ScreenUpdating = False
' Get a reference to the sheet you want to process
Set sh = ActiveSheet
' Get a reference to the range of cells to test, plus header row
With sh
Set rng = .Range(.Cells(7, 1), .Cells(.Rows.Count, 1).End(xlUp))
End With
' Apply filr to hide non-empty cells
sh.AutoFilterMode = False
rng.AutoFilter Field:=1, Criteria1:="=", VisibleDropDown:=True
' if there are no blanks SpecialCells will error, so handle it
On Error Resume Next
' Reduce rng to reference only blank cells, exclude header row
Set rngBlanks = rng.Offset(1, 0).SpecialCells(xlCellTypeVisible)
On Error GoTo 0
' see if there are any blanks
If Not rngBlanks Is Nothing Then
' delete all of them
rngBlanks.EntireRow.Delete
End If
sh.AutoFilterMode = False
Application.ScreenUpdating = True
End Sub
So basically, if it comes across a blank row, it should delete that row and all the rows below it.
For deleting all the rows below, you could essentially do the same thing that happens when you press CTRL and the down arrow - it goes to either the next value down (if there is one, and in your case it sounds like there won't be) or to the end (row 65536 is the limit in all the Excel versions I've come across). Which would be...
Range(Selection, Selection.End(xlDown)).Select
Selection.Delete Shift:=xlUp
This will go from the row you've selected (so no need to delete it), down to either the next value or the end, and delete all those rows.
EDIT - entire macro:
Dim i As Integer
For i = 1 To 93
Range("A" & i).Select
Dim CheckVal As String
CheckVal = ActiveCell.Value
If (CheckVal = "") Then
Range(Selection, Selection.End(xlDown)).Select
Selection.Delete Shift:=xlUp
End If
Next i
Bear in mind though that, if there ARE any values below the first "blank" that is found, they are deleted too as the first contiguous value.

Resources