VBA- Need to loop through only visible cells - excel

Trying to copy specific cells only from filtered rows, but this part of code keeps copying all data even from hidden cells.
Sheets(Wss).Range("A1").AutoFilter _
Field:=8, _
Criteria1:="Vesztesg", _
VisibleDropDown:=False
For j = 2 To Sheets(Wss).Range("A2").End(xlDown).End(xlDown).End(xlUp).Row - 1
Sheets("EBS Posting template").Range("C" & i) = Sheets(Wss).Range("E" & j)
Sheets("EBS Posting template").Range("O" & i + 1) = Sheets(Wss).Range("F" & j)
Sheets("EBS Posting template").Range("G" & i + 2) = Sheets(Wss).Range("J" & j)
i = i + 3
Next j

To loop through visible cells only, you need to loop through a range.
So instead of For i loop we use For Each that will let you do that. We add .SpecialCells(xlCellTypeVisible) to that range.
For each element in the range we declare a variable, cl. which we can use to extract data from.
Sheets(Wss).Range("A1").AutoFilter _
Field:=8, _
Criteria1:="Vesztesg", _
VisibleDropDown:=False
Dim cl As Range
For Each cl In Range(Cells(2, 1), Cells(Sheets(Wss).Range("A2").End(xlDown).End(xlDown).End(xlUp).Row - 1, 1)).SpecialCells(xlCellTypeVisible) 'Apply visible cells only
j = cl.Row 'row number of current cl value.
Sheets("EBS Posting template").Range("C" & i) = Sheets(Wss).Range("E" & j)
Sheets("EBS Posting template").Range("O" & i + 1) = Sheets(Wss).Range("F" & j)
Sheets("EBS Posting template").Range("G" & i + 2) = Sheets(Wss).Range("J" & j)
i = i + 3
Next cl 'loop to next cl

If you are using a counter to the rows, even if the row is hidden, it is still going to give you that row value.
You would require additional lines to make sure that row was not hidden.
Possibly just looping through the visible cells would suffice.
By the way: I am not sure where your values are ending up, you will have to edit that in your code.
The code will loop through the visible cells in column E, check the sheet name in the code as well, I wasn't sure about that either.
Sub Button2_Click()
Dim wss As Worksheet, sh As Worksheet, LstRw As Long, rng As Range, c As Range, Lr As Long
Set wss = Sheets("Sheets(Wss)")
Set sh = Sheets("EBS Posting template")
With wss
LstRw = .Cells(.Rows.Count, 8).End(xlUp).Row
.Range("A1").AutoFilter Field:=8, Criteria1:="Vesztesg"
Set rng = .Range("E2:E" & LstRw).SpecialCells(xlCellTypeVisible)
For Each c In rng.Cells
With sh
Lr = .Cells(.Rows.Count, "C").End(xlUp).Row + 1
.Cells(Lr, "C").Value = c
.Cells(Lr, "O").Value = c.Offset(, 1)
.Cells(Lr, "G").Value = c.Offset(, 5)
End With
Next c
.AutoFilterMode = False
End With
End Sub

Related

Selection of Continued filled Cells and Calculation of MAX,MIN,AVG

Hope You are all Safe
I'm trying to calculate MAX, MIN and AVG Values of filled cells which are continued without blank cell (As you can see it in the left side of the sample image ).
I'm facing problem in selecting these randomly placed cells and calculate the above values and also "From" and "To" values of respective range.
Please let me know how to do it. So far I've constructed following code
Dim Cel As Range
Dim lastrow As Long
Dim destSht As Worksheet
Set destSht = Worksheets("Final")
With Worksheets("Source")
lastrow = .Range("B" & .Rows.Count).End(xlUp).Row
For Each Cel In .Range("C2:C" & lastrow)
If .Cells(Cel.Row, "C") <> "" Then
Cel.Offset(0, -1).Copy Destination:=destSht.Cells(destSht.Rows.Count, 1).End(xlUp).Offset(0, 1)
'It will give "From" Column
'' Plz suggest for "To" Column
Range("G5").Select
ActiveCell.FormulaR1C1 = "=MAX(RC[-4]:R[4]C[-4])" 'It will give values "MAX" Column
Range("H5").Select
ActiveCell.FormulaR1C1 = "=MIN(RC[-5]:R[4]C[-5])" 'It will give values "MIN" Column
Range("I5").Select
ActiveCell.FormulaR1C1 = "=AVERAGE(RC[-6]:R[4]C[-6])" 'It will give values "AVG" Column
End If
Next
Did some quick, which should work.
I don't know what you want to do in the "Final" worksheet, so haven't focused on that line.
Logic is to have one big loop (For i...) that go through the whole Column C. When a value is found in column C (If .Cells(i, "C") <> "" Then), we perform a "small loop" (For j = i To lastrow + 1) to check next empty cell to decide the "small group" range. When that range is decided we perform the To, From, MAX, MIN and AVG formulas, which has to be dynamic.
Option Explicit
Sub trial()
Dim lastrow As Long
Dim destSht As Worksheet
Dim i As Long, j As Long
Set destSht = Worksheets("Final")
With Worksheets("Source")
lastrow = .Range("B" & .Rows.Count).End(xlUp).Row
For i = 2 To lastrow + 1 'loop whole range (column C)
If .Cells(i, "C") <> "" Then 'If column C is not empty then
For j = i To lastrow + 1 'Loop "group" range to find next empty cell. Start from current loop i to last row and add one row to get to next empty cell.
If .Cells(j, "C") = "" Then 'When next empty cell is found (i.e. end of small group range) then apply formulas
.Cells(i, "E").Value = .Cells(i, "B").Value 'From
.Cells(i, "F").Value = .Cells(j - 1, "B").Value 'To
.Cells(i, "G").Formula = "=MAX(C" & i & ":C" & j - 1 & ")" 'MAX
.Cells(i, "H").Formula = "=MIN(C" & i & ":C" & j - 1 & ")" 'MIN
.Cells(i, "I").Formula = "=AVERAGE(C" & i & ":C" & j - 1 & ")" 'AVG
Exit For
End If
Next j
End If
Next i
End With
End Sub
Result:

Avoid copying buttons in range

i have a macro where i copy paste a range, which also has buttons in there.
Now i dont want the buttons to get copied. How can i do that?
I copy the whole table and insert it again at A32.
lrow = .Cells(Rows.Count, 1).End(xlUp).row
Do While counter = 0
For i = 32 To lrow
If .Cells(i, 1).Value = "Review Participants" And counter = 1 Then
lastrev = lrowrev
lrowrev = i - 1 'row where the second last review starts
aboveR = lrowrev - lastrev
Exit For
ElseIf .Cells(i, 1).Value = "Review Participants" And counter <> 1 Then
counter = counter + 1
lrowrev = i
lcol = 11 'hardcode last col ~~ Alt: 'lcol = .Cells(i + 1, .Columns.Count).End(xlToLeft).Column 'last meeting of the review is our reference for lastcol
ElseIf counter = 1 And i = lrow Then
lrowrev = i + 2
aboveR = (i + 2) - 32
Exit For
End If
Next
Loop
lastcolumn = Split(Cells(, lcol).Address, "$")(1)
Set rngtocopy = .Range("A" & 32 & ":" & lastcolumn & lrowrev)
Debug.Print rngtocopy.Address
'aboveR = .Range("A" & 32 & ":" & lastcolumn & lrowrev - 1).Rows.Count ' amount of rows copied
Set rngins = .Range("A32").EntireRow
Debug.Print rngins.EntireRow.Resize(aboveR + 2).Address
rngins.EntireRow.Resize(aboveR + 2).Insert xlShiftDown 'insert the amount of rows, we copied
'Range("A" & lrow).Offset(5).EntireRow.Hidden = False
Set rngins = .Range("A32")
Debug.Print rngins.Address
rngtocopy.Copy
rngins.PasteSpecial Paste:=xlPasteAll
Try this code, please:
Sub copyRangeNoButt()
Dim sh As Worksheet, rng As Range, arrRng As Variant
Set sh = ActiveSheet
Set rng = sh.Range("D2:E10"): rng.Copy
arrRng = rng.value
With sh.Range("H2").Resize(UBound(arrRng, 1), UBound(arrRng, 2))
.value = arrRng
.PasteSpecial xlPasteFormats'comment this line if format is not needed. It takes much more time than all the rest of the code, in case of a big range...
End With
End Sub
Of course, you must adapt the code to use your range to be copied definition and the cell where to be pasted (even if in another worksheet).
Now i dont want the buttons to get copied. How can i do that?
You can also use PasteSpecial. You can take advantage of XlPasteType enumeration to copy and paste only relevant part. For example, here is a one liner in case you want to paste
A. Everything except the image
rng.PasteSpecial Paste:=xlPasteAllUsingSourceTheme
B. Only Values
rng.PasteSpecial Paste:=xlPasteValues
In action

Copy ranges and multiply in loop

Ive been searching left and right but seem to only find bits and pieces. i'm unable to combine these into the solution i need.
My workbook has a list of items on the first sheet, the partnumbers in column A have to be searched for in Column A of a second sheet and if they exist there, those rows need to be copied to a third sheet.In steps i'm looking to do the following:
Column A of sheet1 (called "input") has several partnumbers.
After clicking CommandButton2 on sheet1, all partnumbers in Column A (starting in cell A5)should be searched for in Column A of sheet3 (called "partlists", starting in A2).
If found here, for all the respective rows where the partnumbers match: columns C to G("partlists") should be copied to sheet2("picklist") column A below the last row, the value in column E("picklist") has to be multiplied with the value in Column E("input") AND columns G to K("input") copied to the respective rows column G("Picklist")
If not found on "partlists", copy entire row from "input" to "picklist" below last row.
So far i've got the following code:
Sub InputPickMatch()
Dim LR As Long, i As Long, lngNextRow As Long, LookUpListInput As Range, LookUpListParts As Range
Set LookUpListInput = Sheets("Input").Range("A:A") 'lookup list Input
Set LookUpListParts = Sheets("Partlists").Range("A:A")
With Sheets("Input")
LR = .Cells(Rows.Count, "A").End(xlUp).Row 'last row
For i = 5 To LR
If IsError(Application.Match(.Cells(i, "A").Value, LookUpListParts, 0)) Then
.Range(Cells(i, "A").Address(), Cells(i, "D").Address()).Copy
Sheets("Picklist").Select
lngNextRow = Sheets("Picklist").Range("A" & Rows.Count).End(xlUp).Row + 1
Sheets("Picklist").Range("A" & lngNextRow).PasteSpecial _
Paste:=xlPasteValues
.Range(Cells(i, "F").Address(), Cells(i, "K").Address()).Copy
Sheets("Picklist").Range("E" & lngNextRow).PasteSpecial _
Paste:=xlPasteValues
End If
Next i
End With
With Sheets("Partlists")
LR = .Cells(Rows.Count, "A").End(xlUp).Row 'last row
For i = 3 To LR
If IsNumeric(Application.Match(.Cells(i, "A").Value, LookUpListInput, 0)) Then
.Range(Cells(i, "C").Address(), Cells(i, "G").Address()).Copy
Sheets("Picklist").Select
lngNextRow = Sheets("Picklist").Range("A" & Rows.Count).End(xlUp).Row + 1
Sheets("Picklist").Range("A" & lngNextRow).PasteSpecial _
Paste:=xlPasteValues
'Sheets("Picklist").Cells(lngNextRow, "E") = Sheets("Input").Cells(LookUpListInput, "E") * .Cells(i, "G") 'NOT WORKING: Multiply row from lookuplist column E with .Cells(i, "G")
'Sheets("Input").Range(Cells(LookUpList, "G").Address(), Cells(LookUpListInput, "K").Address()).Copy 'NOT WORKING: Copy row from lookuplist column G:K
'Sheets("Picklist").Range("F" & lngNextRow).PasteSpecial 'Paste Picklist column G
End If
Next i
End With
End Sub
It's working ok up to where i try to multiply and copy from the lookup list.
Hopefully someone can help
I got it guys
Sub InputToPicklist()
Dim LR As Long, i As Long, lngNextRow As Long, LookUpListInput As Range, LookUpListParts As Range
Dim Matchres As Variant
Set LookUpListInput = Sheets("Input").Range("A:A")
Set LookUpListParts = Sheets("Partlists").Range("A:A")
With Sheets("Input")
LR = .Cells(Rows.Count, "A").End(xlUp).Row
For i = 5 To LR
If IsError(Application.Match(.Cells(i, "A").Value, LookUpListParts, 0)) Then
lngNextRow = Sheets("Picklist").Range("A" & Rows.Count).End(xlUp).Row + 1
Sheets("Picklist").Range(Cells(lngNextRow, "A").Address(), Cells(lngNextRow, "D").Address()).Value = .Range(Cells(i, "A").Address(), Cells(i, "D").Address()).Value
Sheets("Picklist").Range(Cells(lngNextRow, "E").Address(), Cells(lngNextRow, "J").Address()).Value = .Range(Cells(i, "F").Address(), Cells(i, "K").Address()).Value
End If
Next i
End With
With Sheets("Partlists")
LR = .Cells(Rows.Count, "A").End(xlUp).Row 'last row
For i = 3 To LR
If IsNumeric(Application.Match(.Cells(i, "A").Value, LookUpListInput, 0)) Then
lngNextRow = Sheets("Picklist").Range("A" & Rows.Count).End(xlUp).Row + 1
Sheets("Picklist").Range(Cells(lngNextRow, "A").Address(), Cells(lngNextRow, "E").Address()).Value = .Range(Cells(i, "C").Address(), Cells(i, "G").Address()).Value
Matchres = Application.Match(.Cells(i, "A").Value, LookUpListInput, 0)
Sheets("Picklist").Cells(lngNextRow, "E") = Sheets("Input").Cells(Matchres, "F") * .Cells(i, "G") 'Multiply row from lookuplist column E with .Cells(i, "G")
Sheets("Picklist").Range(Cells(lngNextRow, "F").Address(), Cells(lngNextRow, "J").Address()).Value = Sheets("Input").Range(Cells(Matchres, "G").Address(), Cells(Matchres, "K").Address()).Value 'Copy row from lookuplist column G:K
End If
Next i
End With
Sheets("Input").Range("A5:K138").ClearContents
End Sub
First
Dim Matchres As Variant
and calling it
Matchres = Application.Match(.Cells(i, "A").Value, LookUpListInput, 0)
Does the trick

How to get the sum of two adjacent columns into one merged cell (VBA)?

I am creating a summary macro and I need to add up all the values of column C and D into the merged cell in E. In the image attached the sums are already placed to show the result I want. I already have code to merge the cells in column E based on the names in A. IE Sum up all overdue and critical for bob and place in merged column, then nick. Here is what I have I just need help getting the sum:
Sub MergeSameCell()
Dim Rng As Range, xCell As Range
Dim xRows As Integer
Set WorkRng = ThisWorkbook.Worksheets("Summary").Range("A:A")
lastRow = ActiveSheet.Columns("A").Cells.Find("*", SearchOrder:=xlByRows,
LookIn:=xlValues, SearchDirection:=xlPrevious).Row
xRows = lastRow
For Each Rng In WorkRng.Columns
For i = 1 To xRows - 1
For j = i + 1 To xRows
If Rng.Cells(i, 1).Value <> Rng.Cells(j, 1).Value Then
Exit For
End If
Next
WorkRng.Parent.Range(Rng.Cells(i, 5), Rng.Cells(j - 1, 5)).Merge
i = j - 1
Next
Next
End Sub
The below uses your enclosed data specifically and assumes the data has already been sorted by column A and the cells in column E are already merged.
Public Sub GroupSum()
Dim i0 As Long, i1 As Long, strName As String
With ActiveSheet
For i0 = 2 To .UsedRange.Rows.Count
If Not .Cells(i0, 1).Value = strName Then
strName = .Cells(i0, 1)
i1 = i0
End If
.Cells(i1, 5).Value = .Cells(i0, 3).Value + .Cells(i0, 4).Value + .Cells(i1, 5).Value
Next i0
End With
End Sub
I will leave the alignment formatting of the merged cells to you.
Option Explicit
Sub MergeSameCell()
Dim clientRng As Range
Dim lastRow As Long, lastClientRow As Long
With ThisWorkbook.Worksheets("Summary")
.Columns(5).UnMerge
Set clientRng = .Range("A2")
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
Do
lastClientRow = .Columns(1).Find(what:=clientRng.Value, after:=clientRng, _
lookat:=xlWhole, SearchDirection:=xlPrevious).Row
With clientRng.Offset(0, 4)
.Resize(lastClientRow - clientRng.Row + 1, 1).Merge
.Formula = "=sumifs(c:c, a:a, " & Chr(34) & clientRng.Value2 & Chr(34) & ")+" & _
"sumifs(d:d, a:a, " & Chr(34) & clientRng.Value2 & Chr(34) & ")"
'optionally revert the formulas to their returned value
'value = .value2
End With
Set clientRng = clientRng.Offset(lastClientRow - clientRng.Row + 1, 0)
Loop While clientRng.Row <= lastRow
End With
End Sub
This removes a couple of loops:
Sub MergeSameCell()
With ThisWorkbook.Worksheets("Summary")
Dim i as Long
For i = 2 To .Rows.Count
If .Cells(i, 1) = "" Then Exit Sub
Dim x As Long
x = .Evaluate("MATCH(TRUE," & .Cells(i, 1).Address & "<>" & .Range(.Cells(i, 1), .Cells(.Rows.Count, 1)).Address & ",0) - 2 + " & i)
.Cells(i, 5).Value = Application.Sum(.Range(.Cells(i, 3), .Cells(x, 4)))
.Range(.Cells(i, 5), .Cells(x, 5)).Merge
i = x
Next i
End With
End Sub

Unable to get the match property of the WorkSheet function class - Syntax?

I keep getting this error on the line with Application.WorksheetFunction and from reading on the topic for hours I feel that I've gotten just about nowhere.
Does it have something to do with the way I'm referencing Sheet2? Or am I not understanding fully what Application.WorksheetFunction is supposed to do?
Sub SearchForValues()
i = 4 'starts the iterator at column D
Do While Cells(1, i) <> ""
Dim l As Long, searchRange As String
n = 2
Do While Range("A" & n) <> "" 'loop until the last row of data in the first column
StartRow = Range("B" & n)
EndRow = Range("C" & n)
searchRange = "A" & StartRow & ":Q" & EndRow
l = Application.WorksheetFunction.Match(Cells(1, i), Worksheets("Sheet2").Range(searchRange), 0)
Range("D" & n) = l
n = n + 1
Loop
i = i + 1
Loop
End Sub
Here's a screenshot of the data I have. Columns B and C are the ranges of rows that I want to search in on Sheet2 for each row on sheet 1 and each cell across the top is a term I want to search for in that range.
Scott Craner already answered your question in his comments with "
Match only works on 1 dimensional arrays; either one row or one column" and "Use the VBA Find()".
Here is an example of how you can use Range.Find
Sub SearchForValues()
Application.ScreenUpdating = False
Dim Target As Range
Dim x As Long, y As Long
With Worksheets("Sheet1")
For x = 2 To .Cells(.Rows.Count, 1).End(xlUp).Row
For y = 4 To .Cells(1, .Columns.Count).End(xlToLeft).Column
Set Target = Worksheets("Sheet2").Range("A" & .Cells(x, "B").Value & ":Q" & .Cells(x, "C").Value)
.Cells(x, y).Value = Not Target.Find(.Cells(1, y).Value) Is Nothing
Next
Next
End With
Application.ScreenUpdating = True
End Sub

Resources