Copy Cells Greater than Zero, and Paste Values in same Cell - excel

I have a table that is filled with formulas tied to another sheet. These formulas grab data from the other table based on whether the date at the top of the column matches the date in a single cell (Week Ending Date). I want to be able to automatically copy only the cells with a value greater than 0, and then paste them back into the same cell as a value. I used the following formula to try and accomplish this, but it didn't quite do what I wanted it to. Be gentle, I'm a novice at best.
Sub CopyC()
Dim SrchRng As Range, cel As Range
Set SrchRng = Range("Table4")
For Each cel In SrchRng
If cel.Value > 0 Then
cel.Copy
cel.PasteSpecial xlPasteValues
End If
Next cel
End Sub
Expected Output: Copy only Cells in my table that are greater than 0 and paste as value.
Goal: Preserve Formulas in cells that are blank
Results from above: Very slowly progressed cell by cell and copied and pasted in all cells, including blanks and 0 values, until it was stopped

Give this a try:
Sub CopyC()
Dim SrchRng As Range, cel As Range
Set SrchRng = Range("Table4")
For Each cel In SrchRng
If IsNumeric(cel.Value) And cel.Value > 0 Then
cel.Value = cel.Value
End If
Next cel
End Sub
EDIT: add an alternative using an array to loop through the data, this should be a bit faster:
Sub CopyC()
Dim SrchRng As Range: Set SrchRng = Range("Table4")
Dim arrSearch As Variant: arrSearch = SrchRng
Dim fRow As Long: fRow = SrchRng.Cells(1, 1).Row - 1
Dim fCol As Long: fCol = SrchRng.Cells(1, 1).Column - 1
Dim R As Long, C As Long
For R = LBound(arrSearch) To UBound(arrSearch)
For C = LBound(arrSearch, 2) To UBound(arrSearch, 2)
If IsNumeric(arrSearch(R, C)) And arrSearch(R, C) > 0 Then Cells(R + fRow, C + fCol).Value = arrSearch(R, C)
Next C
Next R
End Sub

Related

VBA Look down column to find specific criteria then SUM cell after criteria met cell

Currently, I'm trying to figure a way to look down a single column to find a specific criterion and in this case, I want to find dates that are less than 4/16/20. Once that criteria is met, I want to SUM the cell below for all met criteria in that column. This is an image of my dataset
.
After doing some googling the closest I found was the code below which leads me to the idea that change information after offset to compute what I want.
Using "If cell contains" in VBA excel
Sub AddDashes()
Dim SrchRng As Range, cel As Range
Set SrchRng = Range("RANGE TO SEARCH")
For Each cel In SrchRng
If InStr(1, cel.Value, "TOTAL") > 0 Then
cel.Offset(1, 0).Value = "-"
End If
Next cel
End Sub
Not sure if I'm on the right track. It would also be nice If I would be able to amend code to check a range vs 1 column, thanks.
In this example you need to select the range of dates (1 row at a time only) to run the code. This also allows you to input the date (I'm assuming it changes over time so this should be helpful)
Sub SumByDate()
Dim DateRange As Range
Dim c As Range
Dim d As Range
Dim SearchDateInput As String
Dim SearchDate As Date
Set DateRange = Application.InputBox("Select a range", "Get Range", Type:=8) 'Select Date Range
SearchDateInput = Application.InputBox("Enter A Date") 'enter as mm/dd/yyyy
SearchDate = DateValue(SearchDateInput) 'this converts date entered as string to date format
For Each c In SrchRng 'for each date in list of dates
Set d = c.Offset(1, 0) 'pionts out cells to sum- in this case the cell beneath the date
If c < SearchDate Then 'if date is less than input date
Sum = Sum + d 'sum the date if true
End If
Next c 'goes to next date in row
DateRange.Cells(1, 1).Offset(2, -1) = Sum 'inputs all summed values into cell that is two down, one to the left of first date cell
End Sub
Sub SumByDate()
Dim SrchRng As Range
Dim c As Range
Dim d As Range
Dim lCol As Long
Dim ColLtr As String
Dim SearchDate As Date
lCol = Cells(2, Columns.Count).End(xlToLeft).Column
ColLtr = Split(Cells(1, lCol).Address, "$")(1)
Set SrchRng = Range("B2:" & ColLtr & "2")
SearchDate = DateValue("04/16/2020")
For Each c In SrchRng
Set d = c.Offset(1, 0)
If c < SearchDate Then
Sum = Sum + d
End If
Next c
Range("A4") = Sum
End Sub

object not found - copy excel range from one sheet to other

Private Sub CommandButton1_Click()
Dim cel As Range, lRow As Long
'next line determines the last row in column 1 (A), of the first Worksheet
lRow = Worksheets("Delta").UsedRange.Columns(5).Rows.Count
'iterate over every cell in the UsedRange
For Each cel In Worksheets("Delta").Range("E10:E" & lRow)
'cel represents the current cell
'being processed in this iteration of the loop
'Len() determines number of characters in the cell
If Len(cel.Value2) > 0 Then
'if cel is not empty, copy the value to the cell range (D1,D2,D3...) mentioned
Sheets("Traceability").Select
Traceability.Range("D3:D100").Select = cel.Value2 '--->Object not defined
End If
Next 'move on the next (lower) cell in column 1
End Sub
For copying a range of data I am facing an error of object not defined. Is my method to copy cell values correct ?
This is what I came up to finally
Private Sub CommandButton1_Click()
Dim cel As Range, lRow As Long
Dim i As Integer
lRow = Worksheets("Delta").UsedRange.Columns(5).Rows.Count
rw = 3
'iterate over every cell in the UsedRange
For Each cel In Worksheets("Delta").Range("E10:E" & lRow)
If Len(cel.Value2) > 0 Then
'if cel is not empty, copy the value to the cell
Sheets("Traceability").Range("D" & rw).Value = cel.Value2
rw = rw + 1
End If
Next
End Sub
try:
Remove:
Sheets("Traceability").Select
Change:
Traceability.Range("D3:D100").Select = cel.Value2
to
Sheets("Traceability").Range("D3:D100") = cel.Value2
Its been a while since i had to do this, but if i remember right, selecting the worksheet does not assign it to a variable.
You've selected Traceability worksheet, then you try to do things on "Traceability" without telling it what "Traceability" is.
If that makes sense.

Loop to replace values greater than 0

Sorry I am a novice in VBA so any help is gratefully received!
I'm looking for some VBA code for a loop that will look at a range in Column A and as long as the cell in Column A is not 0, replace the adjacent cell in Column B with the positive value, looping through the range until all cells with data > 0 in Column A have been replaced in Column B. It is also important that blank cells in Column A do not overwrite positive data that may exist in Column B.
This is where I am at the moment:
Sub Verify()
Dim rng As Range
Dim i As Long
'Set the range in column N
Set rng = Range("N2:n1000")
For Each cell In rng
'test if cell = 0
If cell.Value <> 0 Then
'write value to adjacent cell
cell.Offset(0, -2).Value = *'What do I need here to find the first item of data e.g. N2 in column N?'*
End If
Next
End Sub
Many thanks
I think it would be easier to deal with ActiveSheet.Cells as with Range object and offsets :
Sub Verify()
Dim row As Long
For row = 2 To 1000
If ActiveSheet.Cells(row,1) <> "" Then ' Not blank
If ActiveSheet.Cells(row,1) > 0 Then ' Positive
ActiveSheet.Cells(row,2) = ActiveSheet.Cells(row,1)
End If
End If
Next
End Sub
This is the edit to what you started. I made the range dynamic, because I don't like making excel loop longer than it has to. That's my personal preference. The first block of code will copy over anything that isn't 0 or blank, and any negative numbers will be represented by their positive counterpart. That's at least how I understood your question.
Also, this code looks at data in Col N (like you have in your code) and copies the data to Col L. If you want A to B then simply change rng to = ws.Range("A2", ws.Cells(ws.Rows.Count, "A").End(xlUp)) and the myCell.Offset() to (0, 1).
Sub Verify()
Dim ws As Worksheet
Dim rng As Range
Set ws = ThisWorkbook.Sheets(1) 'good form to always define the sheet you're working on
Set rng = ws.Range("N2", ws.Cells(ws.Rows.Count, "N").End(xlUp)) 'dynamic range
For Each myCell In rng
If myCell.Value <> "" And myCell.Value <> 0 Then 'If the cell isn't 0 or ""
If myCell.Value < 0 Then 'Then if it's negative, make it positive and copy it over
myCell.Offset(0, -2).Value = myCell.Value * -1
Else: myCell.Offset(0, -2).Value = myCell.Value 'otherwise copy the value over
End If
End If
Next myCell
End Sub
If you only want to copy over values that are greater than 0, and ignore 0's, blanks, and negative values, then use this code:
Sub Verify()
Dim ws As Worksheet
Dim rng As Range
Set ws = ThisWorkbook.Sheets(1) 'good form to always define the sheet you're working on
Set rng = ws.Range("N2", ws.Cells(ws.Rows.Count, "N").End(xlUp)) 'dynamic range
For Each myCell In rng
If myCell.Value <> "" And myCell.Value > 0 Then 'If the cell is > 0 and not ""
myCell.Offset(0, -2).Value = myCell.Value 'copy the value over
End If
Next myCell
End Sub
If I understand your question correctly, you can "simplify" it to something like this:
Sub Verify()
[b2:b1000] = [if(iferror(-a2:a1000,),abs(a2:a1000),b2:b1000&"")]
End Sub
just replace a2:a1000 with your Column A range and b2:b1000 with the Column B range.

copy cell if it contains text

Data is transferred from a web-form to Excel. Not every cell receives inputs. There are many cells, it is time consuming to scan each cell looking for text.
How do I get the text automatically copied from sheet1 to sheet2. But I don't want the cells displayed in the same layout as the original sheet. I would like them to be grouped together, eliminating all of the empty cells in between. I would also like to grab the title from the row that contains the text.
I found this macro:
Sub CopyC()
Dim SrchRng As Range, cel As Range
Set SrchRng = Range("C1:C10")
For Each cel In SrchRng
If cel.Value <> "" Then
cel.Offset(2, 1).Value = cel.Value
End If
Next cel
It grabs only cells that contain text, but it displays it in the exact same layout that it found it in. Any help would be appreciated and save me a lot of scan time in the future, thanks in advance :)
I guess this is what you are looking for:
Sub CopyNonBlankCells()
Dim cel As Range, myRange As Range, CopyRange As Range
Set myRange = Sheet1.Range("C1:C20") '---> give your range here
For Each cel In myRange
If Not IsEmpty(cel) Then
If CopyRange Is Nothing Then
Set CopyRange = cel
Else
Set CopyRange = Union(CopyRange, cel)
End If
End If
Next cel
CopyRange.Copy Sheet2.Range("C1") '---> enter desired range to paste copied range without blank cells
End Sub
Above code will copy range C1:C20 in Sheet1 to C1 in Sheet2
Got this from here.
EDIT: Following answer is based on your comment
________________________________________________________________________________
If you'll write something like below
Set myRange = Sheet1.Range("G:G")
Set myRange = Sheet2.Range("G:G")
myRange will be first set to Sheet1.Range("G:G") and then to Sheet2.Range("G:G") that means current range that myRange will have is Sheet2.Range("G:G").
If you want to use multiple ranges you can go for UNION function but there's a limitation that using UNION, you can combine different ranges but of only one sheet. And your requirement is to combine ranges from different sheets. To accomplish that I am adding a new worksheet and adding your G:G ranges from all the sheets to it. Then after using newly added sheet I am deleting it.
Following code will give you the desired output in the sheet named Result.
Sub CopyNonBlankCells()
Dim cel As Range, myRange As Range, CopyRange As Range
Dim wsCount As Integer, i As Integer
Dim lastRow As Long, lastRowTemp As Long
Dim tempSheet As Worksheet
wsCount = Worksheets.Count '--->wsCount will give the number of Sheets in your workbook
Set tempSheet = Worksheets.Add '--->new sheet added
tempSheet.Move After:=Worksheets(wsCount + 1)
For i = 1 To wsCount
If Sheets(i).Name <> "Result" Then '---> not considering sheet "Result" for taking data
lastRow = Sheets(i).Cells(Rows.Count, "G").End(xlUp).Row '--->will give last row in sheet
lastRowTemp = tempSheet.Cells(Rows.Count, "G").End(xlUp).Row '--->will give last row in newly added sheet
Sheets(i).Range("G1:G" & lastRow).Copy _
tempSheet.Range("G" & lastRowTemp + 1).End(xlUp)(2)
End If
Next i
lastRowTemp = tempSheet.Cells(Rows.Count, "G").End(xlUp).Row
Set myRange = tempSheet.Range("G1:G" & lastRowTemp) '--->setting range for removing blanks cells
For Each cel In myRange
If Not IsEmpty(cel) Then
If CopyRange Is Nothing Then
Set CopyRange = cel
Else
Set CopyRange = Union(CopyRange, cel)
End If
End If
Next cel
CopyRange.Copy Sheets("Result").Range("G1") '---> enter desired range to paste copied range without blank cells
Application.DisplayAlerts = False
tempSheet.Delete '--->deleting added sheet
Application.DisplayAlerts = True
End Sub
You can use arrays!
Instead of copying information from one cell to another, you can store all your information in an array first, then print the array on another sheet. You can tell the array to avoid empty cells. Typically, using arrays is the best way to store information. (Often the fastest way to work with info)
If you are only looking at one column, you could use a one-dimensional array. If you are looking at multiple columns, and want to print the information into the corresponding column (but different cells) in another page then you could a multi-dimensional array to store column number/anything else you wanted.
From your code, it could look like this:
Sub CopyC()
Dim SrchRng As Range, cel As Range
'Declare your 1-d array (I don't know what you are storing)
Dim myarray() as variant
Dim n as integer
Dim i as integer
Set SrchRng = Range("C1:C10")
'define the number of elements in the array - 1 for now, increase it as we go
n = 0
Redim myarray(0 to n)
For Each cel In SrchRng
If cel.Value <> "" Then
'redim preserve stores the previous values in the array as you redimension it
Redim Preserve myarray(0 to n)
myarray(n) = cel.Value
'increase n by 1 so next time the array will be 1 larger
n = n + 1
End If
Next cel
'information is now stored, print it out in a loop
'this will print it out in sheet 2 providing it is called "Sheet2"
For i = 0 to ubound(myarray)
Sheets("Sheet2").cells(i,1).value = myarray(i)
Next i

Excel VBA Highlight duplicates in active column

I'm trying to create a macro that will highlight duplicates in the column where text is being entered.
I have 54 columns and want to highlight duplicates in each column as the text is entered. The scenario is: if "STAPLES" is entered twice in column B then the cells (B3, B22) would be highlighted. I want a macro that can do this for each column, so if "STAPLES" is entered into column E only once nothing should happen.
Using the Conditional Formatting =COUNTIF doesn't necessarily help (due to the workflow of copying columns to new worksheets).
I have this macro already:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim Rng As Range
Dim cel As Range
'Test for duplicates in a single column
'Duplicates will be highlighted in red
Set Rng = Range(Range("C1"), Range("C" & Rows.Count).End(xlUp))
For Each cel In Rng
If WorksheetFunction.CountIf(Rng, cel.Value) > 1 Then
cel.Interior.ColorIndex = 3
End If
Next cel
End Sub
It works ok but is only for one column ("C").
How do I set the range to be the active column?
I have tried to change Rng to
'Set Rng = Range(ActiveCell,ActiveCell.Column.End(xlUp))
but this is obviously wrong.
Any ideas?
Try this one:
Set Rng = Range(Cells(1, Target.Column), Cells(Rows.Count, Target.Column).End(xlUp))
and it's better to use Worksheet_Change event instead Worksheet_SelectionChange.
Btw, there is special CF for duplicates:
UPD:
If you'd like to use VBA, try following code:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim Rng As Range
Dim cel As Range
Dim col As Range
Dim c As Range
Dim firstAddress As String
'Duplicates will be highlighted in red
Target.Interior.ColorIndex = xlNone
For Each col In Target.Columns
Set Rng = Range(Cells(1, col.Column), Cells(Rows.Count, col.Column).End(xlUp))
Debug.Print Rng.Address
For Each cel In col
If WorksheetFunction.CountIf(Rng, cel.Value) > 1 Then
Set c = Rng.Find(What:=cel.Value, LookIn:=xlValues)
If Not c Is Nothing Then
firstAddress = c.Address
Do
c.Interior.ColorIndex = 3
Set c = Rng.FindNext(c)
Loop While Not c Is Nothing And c.Address <> firstAddress
End If
End If
Next
Next col
End Sub

Resources