Script to move cell values according to bg colour - excel

The code below is what I have so far. But for some reason it says I have a next soureRow without for. Any help would be great. I'm trying to get this script to loop through sheets 4 to 10 and if the row has a bg colour of yellow or red and sheet one doesnt have a matching value. to copy the row to the bottom of sheet 1.
target = "Sheet1"
For allSheets = 4 To 10
lastTargetRow = Sheets(target).Range("A" & Rows.Count).End(xlUp).Row
Sheets(allSheets).Activate
lastCurrentRow = Sheets(allSheets).Range("A" & Rows.Count).End(xlUp).Row
For sourceRow = 2 To lastCurrentRow
If ActiveSheet.Cells(sourceRow, "B").Interior.Color = Yellow Then
For checkRow = 2 To lastTargetRow
If ActiveSheet.Cells(sourceRow, "B").Value <> Sheets(target).Cells(checkRow, "B").Value Then
nRow = Sheets(target).Range("A" & Rows.Count).End(xlUp).Row + 1
For lCol = 1 To 26 'Copy entire row by looping through 6 columns
Sheets(target).Cells(nRow, lCol).Value = Sheets(allSheets).Cells(sourceRow, lCol).Value
Next lCol
End If
Next checkRow
If ActiveSheet.Cells(sourceRow, "B").Interior.Color = Red Then
For checkRow2 = 2 To lastTargetRow
If ActiveSheet.Cells(sourceRow, "B").Value <> Sheets(target).Cells(checkRow, "B").Value Then
nRow = Sheets(target).Range("A" & Rows.Count).End(xlUp).Row + 1
For lCol = 1 To 26 'Copy entire row by looping through 6 columns
Sheets(target).Cells(nRow, lCol).Value = Sheets(allSheets).Cells(sourceRow, lCol).Value
Next lCol
End If
Next checkRow2
End If
Next sourceRow
Next allSheets

This might get you closer:
Sub Tester()
Const TARGET As String = "Sheet1"
Dim shtTarget As Worksheet, allSheets As Long, nextTargetRow As Long
Dim shtTmp As Worksheet, lastCurrentRow As Long, sourceRow As Long
Dim clr As Long, f As Range, bCell As Range
Dim myYellow As Long '<<EDIT
myYellow = RGB(255, 235, 156)
Set shtTarget = Sheets(TARGET)
nextTargetRow = shtTarget.Cells(Rows.Count, "A").End(xlUp).Row + 1
For allSheets = 4 To 10
Set shtTmp = Sheets(allSheets)
lastCurrentRow = shtTmp.Cells(Rows.Count, "A").End(xlUp).Row
For sourceRow = 2 To lastCurrentRow
Set bCell = shtTmp.Cells(sourceRow, "B")
clr = bCell.Interior.Color 'get the color
'is yellow or red?
If clr = myYellow Or clr = vbRed Then
'look in colB on Target sheet for the value from source
Set f = shtTarget.Columns(2).Find(bCell.Value, lookat:=xlWhole)
If f Is Nothing Then
'ColB value is not already listed
shtTarget.Cells(nextTargetRow, 1).Resize(1, 26).Value = _
shtTmp.Cells(sourceRow, 1).Resize(1, 26).Value
nextTargetRow = nextTargetRow + 1
End If
End If
Next sourceRow
Next allSheets
End Sub

Related

Search Column for Keywords then copy Value to 2 Separate Destination in Sequence

I am trying to improve the workbook macro from my previous thread. I need to do the following:
Limit the search within a range of the worksheet (ex. Sheet 1 B1:N:200)
Search the 8th column (I) of the limit range Sheet1 for keyword ("Goods")
Copy the data found in the 9th column (J) of same row where instance ("Goods") is found
Paste Value of Sheet 1 - column 9 to Sheet2 - Column 7
Search Again 8th column (I) of the limit range Sheet1 for keyword ("Services")
Copy the data found in the 9th column (J) of same row where instance ("Services") is found
Paste Value of Sheet 1 - column 9 to Sheet2 - Column 8
I am trying to self study to understand how the code works and integrate it with code provided by #CDP1802 in previous thread but I can't get how to split result position for the goods and services matches.
Here is the working code provided by #CDP1802 in my previous thread.
Option Explicit
Sub CopyCells()
Const ROW_START = 3
Dim wb As Workbook, ws1 As Worksheet, ws2 As Worksheet
Dim n As Long, r As Long, lastrow1 As Long, lastrow2 as Long
Dim keywords, word, t0 As Single: t0 = Timer
keywords = Array("Goods", "Services")
Set wb = ThisWorkbook
Set ws1 = wb.Sheets(1)
Set ws2 = wb.Sheets(2)
lastrow2 = ROW_START
Application.ScreenUpdating = False
With ws1
lastrow1 = .Cells(.Rows.Count, "I").End(xlUp).Row
For Each word In keywords
For r = 1 To lastrow1
If Len(.Cells(r, "I")) = 0 Then
Exit For
ElseIf .Cells(r, "I") = word Then
'Sht1 col 2 to Sht2 Col 3 (no format values only)
'Sht1 col 5 to Sht2 Col 4 (with format and values)
ws2.Cells(lastrow2, "C") = .Cells(r, "B")
ws2.Cells(lastrow2, "D") = .Cells(r, "E")
.Cells(r, "E").Copy
ws2.Cells(lastrow2, "D").PasteSpecial xlPasteFormats
lastrow2 = lastrow2 + 1
n = n + 1
End If
Next
Next
End With
Application.ScreenUpdating = True
MsgBox r - 1 & " rows scanned " & vbLf & n & " rows copied", _
vbInformation, Format(Timer - t0, "0.0 secs")
End Sub
Here is the code i made to try to do what i need, however I am stump how to use the previous position counter's value for the next argument for "Services" so it follow the next row after the Goods results are done. Current code starts the services result to position 1 again.
in summary I am Looking for a code to integrate desired results in 1 macro for efficiency.
Sub test1code()
Dim lngLastRowSht1 As Long
Dim lngLastRowSht2 As Long
Dim counterSht1 As Long
Dim counterSht2 As Long
Dim resultrow As Long
Const ROW_START = 4
'for Goods data
With Worksheets(1)
resultrow = 1
lngLastRowSht1 = .Cells(.Rows.Count, 4).End(xlUp).Row
lngLastRowSht2 = Worksheets(2).Cells(Worksheets(2).Rows.Count, 5).End(xlUp).Row
For counterSht1 = 1 To lngLastRowSht1 + 1
If Len(Sheets(1).Range("H" & (counterSht1))) = 0 Then
Exit For
ElseIf Sheets(1).Range("H" & (counterSht1)) = "Goods" Then
Sheets(2).Range("F" & (resultrow)).Value = Sheets(1).Range("I" & counterSht1).Value
resultrow = resultrow + 1
End If
Next counterSht1
End With
'for Services data
With Worksheets(1)
resultrow = 1
lngLastRowSht1 = .Cells(.Rows.Count, 4).End(xlUp).Row
lngLastRowSht2 = Worksheets(2).Cells(Worksheets(2).Rows.Count, 5).End(xlUp).Row
For counterSht1 = 1 To lngLastRowSht1 + 1
If Len(Sheets(1).Range("H" & (counterSht1))) = 0 Then
Exit For
ElseIf Sheets(1).Range("H" & (counterSht1)) = "Services" Then
Sheets(2).Range("G" & (resultrow)).Value = Sheets(1).Range("I" & counterSht1).Value
resultrow = resultrow + 1
End If
Next counterSht1
End With
End Sub
Removing resultrow = 1 in the service block of codes so that it will retain the previous row number after looping through for "Goods".
Assuming that the above fix the issue, below is how you can merge both processes into a single block (also removed lngLastRowSht2 as it's not been used and standardize the use of Worksheets and Sheets):
Sub test1code()
Dim lngLastRowSht1 As Long
Dim counterSht1 As Long
Dim counterSht2 As Long
Dim resultrow As Long
Const ROW_START = 4
With Worksheets(1)
resultrow = 1
lngLastRowSht1 = .Cells(.Rows.Count, 4).End(xlUp).Row
'for Goods data
For counterSht1 = 1 To lngLastRowSht1 + 1
If Len(Worksheets(1).Range("H" & counterSht1)) = 0 Then
Exit For
ElseIf Worksheets(1).Range("H" & counterSht1) = "Goods" Then
Worksheets(2).Range("F" & resultrow).Value = Worksheets(1).Range("I" & counterSht1).Value
resultrow = resultrow + 1
End If
Next counterSht1
'for Services data
For counterSht1 = 1 To lngLastRowSht1 + 1
If Len(Worksheets(1).Range("H" & counterSht1)) = 0 Then
Exit For
ElseIf Worksheets(1).Range("H" & counterSht1) = "Services" Then
Worksheets(2).Range("G" & resultrow).Value = Worksheets(1).Range("I" & counterSht1).Value
resultrow = resultrow + 1
End If
Next counterSht1
End With
End Sub

Find all matches in workbook and offset the results into another sheet (VBA)

I'd like some help if possible! Currently, it's causing the excel sheet to crash each time it runs, perhaps because the loop is not ending. Could anyone try helping me fix my code? All 4 sheets have under 5000 rows.
I currently have a workbook with 4 sheets(the number of sheets will change) and one more sheet called Results.
I have managed to look for the string: "Employee Code:-" in Column B, and get the value in Column Y and Column K and paste it in Results A and B respectively. (starting in the 5th row of the Results sheet). (Moving to the next find if Column S and Column K have the same value).
I then would need the values from 3 and 4 rows below the "Employee Code" running from D to AN and pasting it alongside the values from S and K
Then leaving a line after the results have been pasted and repeating for the rest of the find values.
Sub FindAndExecute()
Dim Sh As Worksheet
Dim Loc As Range
Dim i,j As Integer
i = 5
For Each Sh In ThisWorkbook.Worksheets
With Sh.UsedRange
Set Loc = .Cells.Find(What:="Employee Code:-")
If Not Loc Is Nothing Then
Do Until Loc Is Nothing
If Loc.Offset(0, 9).Value <> Loc.Offset(0, 23).Value Then
Sheets("Result2").Cells(i, 1).Value = Loc.Offset(0, 9).Value
Sheets("Result2").Cells(i, 2).Value = Loc.Offset(0, 23).Value
j = 3
Do
Sheets("Result2").Cells(i, j).Value = Loc.Offset(3, j - 1).Value
Sheets("Result2").Cells(i + 1, j).Value = Loc.Offset(4, j -
1).Value
j = j + 1
Loop Until j > 35
i = i + 3
Else
End If
Set Loc = .FindNext(Loc)
Loop
End If
End With
Set Loc = Nothing
Next
End Sub
With FindNext check the search hasn't started again from the beginning.
Sub FandAndExecute2()
Const TEXT = "Employee Code:-"
Const COL_CODE = 2 ' B
Const COL_Y = 25 ' Y
Const COL_K = 11 ' K
' copy from
Const COL_START = "D"
Const COL_END = "AM"
' copy to
Const TARGET = "Result2"
Const START_ROW = 5
Dim wb As Workbook, ws As Worksheet, wsResult As Worksheet
Dim rng As Range, rngSearch As Range, rngCopy As Range
Dim r As Long, iLastRow As Long, iTarget As Long
Dim sFirstFind As String, K, Y, n As Integer
Set wb = ThisWorkbook
Set wsResult = wb.Sheets(TARGET)
iTarget = START_ROW
' scan sheets
For Each ws In wb.Sheets
If ws.Name = TARGET Then GoTo skip
iLastRow = ws.Cells(Rows.Count, COL_CODE).End(xlUp).Row
Set rngSearch = ws.Cells(1, COL_CODE).Resize(iLastRow)
' search for text
With rngSearch
Set rng = .Find(TEXT, LookIn:=xlValues)
If Not rng Is Nothing Then
sFirstFind = rng.Address
Do
r = rng.Row
K = ws.Cells(r, COL_K)
Y = ws.Cells(r, COL_Y)
If K <> Y Then
' copy block
wsResult.Cells(iTarget, "A").Value = K
wsResult.Cells(iTarget, "B").Value = Y
Set rngCopy = ws.Range(COL_START & r + 3 & ":" & COL_END & r + 4)
rngCopy.Copy wsResult.Cells(iTarget, "C")
iTarget = iTarget + 3
n = n + 1
End If
Set rng = .FindNext(rng) ' find next
Loop While Not rng Is Nothing And rng.Address <> sFirstFind
End If
End With
skip:
Next
MsgBox n & " blocks copied to " & wsResult.Name, vbInformation
End Sub

Split cells by line break while keeping other data

I have multiple rows in a spreadsheet set up like the following:
TEST 1 Y N TEST_1 1234 Derived
TEST_2 56
I need to split the cells that have a line break while copying the remaining cells into the new row:
TEST 1 Y N TEST_1 1234 Derived
TEST 1 Y N TEST_2 56 Derived
I tested code by changing line breaks to commas (I don't know the VBA symbol for linebreak). The code I tried only works for one column E, not Column F:
Sub splitByCol()
Dim r As Range, i As Long, ar
Set r = Worksheets("Sheet1").Range("E999999:F999999").End(xlUp)
Do While r.row > 1
ar = Split(r.value, ",")
If UBound(ar) >= 0 Then r.value = ar(0)
For i = UBound(ar) To 1 Step -1
r.EntireRow.Copy
r.Offset(1).EntireRow.Insert
r.Offset(1).value = ar(i)
Next
Set r = r.Offset(-1)
Loop
End Sub
I just did a brief test, might not be perfect. If you have a ton of rows and columns this might be a tad slow aswell.
Dim rowiter As Long
Dim coliter As Long
Dim lastrow As Long
Dim lastcol As Long
Dim rowcount As Long
Dim rowadd As Boolean
With ActiveSheet
lastrow = .Cells(.Rows.Count, "A").End(xlUp).Row
lastcol = .Cells.Find(What:="*", after:=ActiveSheet.Cells(1, 1), LookIn:=xlFormulas, LookAt:= _
xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlPrevious, MatchCase:=False).Column
rowcount = lastrow + 1
For rowiter = 1 To lastrow
rowadd = False
For coliter = 1 To lastcol
If InStr(1, .Cells(rowiter, coliter), vbLf) Then
.Cells(rowcount, coliter).Value = Split(.Cells(rowiter, coliter), vbLf)(1)
.Cells(rowiter, coliter).Value = Split(.Cells(rowiter, coliter), vbLf)(0)
rowadd = True
End If
Next
If rowadd = True Then
For coliter = 1 To lastcol
If .Cells(rowcount, coliter).Value = "" Or IsNull(.Cells(rowcount, coliter).Value) Then
.Cells(rowcount, coliter).Value = .Cells(rowiter, coliter).Value
End If
Next
rowcount = rowcount + 1
End If
rowadd = False
Next
.Range(Cells(1, 1), Cells(rowcount, lastcol)).Sort Key1:=Columns("A"), Order1:=xlDescending
End With
Actually you were almost there:
You need to split by vbLf instead of ","
You need to split column E and F into seperate arrays
So you end up with:
Option Explicit
Sub splitByCol()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1")
Dim CurrentCell As Range
Set CurrentCell = ws.Range("E" & ws.Rows.Count).End(xlUp)
Dim ArrE As Variant 'split array for column E
Dim ArrF As Variant 'split array for column F
Do While CurrentCell.Row > 1
ArrE = Split(CurrentCell.Value, vbLf)
ArrF = Split(CurrentCell.Offset(ColumnOffset:=1).Value, vbLf)
If UBound(ArrE) >= 0 Then CurrentCell.Value = ArrE(0)
If UBound(ArrF) >= 0 Then CurrentCell.Offset(ColumnOffset:=1).Value = ArrF(0)
Dim i As Long
For i = UBound(ArrE) To 1 Step -1
CurrentCell.EntireRow.Copy
CurrentCell.Offset(1).EntireRow.Insert
CurrentCell.Offset(1).Value = ArrE(i)
If UBound(ArrF) >= i Then
CurrentCell.Offset(1, 1).Value = ArrF(i)
Else
CurrentCell.Offset(1, 1).Value = vbNullString
End If
Next i
Set CurrentCell = CurrentCell.Offset(-1)
Loop
End Sub
Input
Output

Copy value from Row and column corresponding to all X'es in sheet

I have a task where i have "Function" in column A, and tags in rows with "X" in middle showing which tag and function is connected together (Please see attachment)
I have been trying to make a script that can go to the "Function (Column A)", check if it will find Value "X" in the same row, if it finds it will go up and get the tag posting the information in new sheet.
Sheet2 will then be showing:
Function -> and thich Tag is in the same function, if there is few tags like in the example below it will show like this.
802AB Tag1
802AB Tag2
802AB Tag3
802AB Tag4
802AB Tag5
804AB Tag4
805AB Tag2
I have few hundrets of those files, which are very big so this is simplified example. Thank you for your help.
https://imgur.com/a/xo0TEZs
Sub test()
Dim rng As Range
Dim cel As Range
Dim lastRow As Long
Dim writeRow As Long
Dim rCell As Range
Dim lColor, ColorRow As Long
Dim rColored As Range
Dim i, j As Integer
Dim temprow As Long
Dim lnRow As Long, lnCol As Long
lColor = RGB(255, 153, 204)
Set rColored = Nothing
lastRow = Sheets("Sheet1").Cells(Rows.Count, "A").End(xlUp).Row
writeRow = Sheets("Sheet2").Cells(Rows.Count, "A").End(xlUp).Row + 1
Set rng = Sheets("Sheet1").Range("A6:A" & lastRow)
For Each cel In rng
If cel.Interior.Color = lColor Then
ColorRow = cel.Row + 1
For j = ColorRow + 1 To lastRow
For i = ColorRow + 1 To lastRow
lnCol = Sheet1.Cells(i, 1).EntireRow.Find(What:="X",
LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlBycolumn,
SearchDirection:=xlNext, MatchCase:=False).Column
' Sheets("Sheet2").Range("A" & writeRow).Value = cel.Offset(0, 0).Value
' writeRow = writeRow + 1
Next i
Next j
'End If
If rColored Is Nothing Then
Else
Sheets("Sheet2").Range("A" & writeRow).Value = cel.Offset(-1, 0).Value
writeRow = writeRow + 1
End If
End If
Next cel
End Sub
This is basically what i have, not yet functional, it searches for the first row with the right format color, then it starts a loop going through rows, searches for X in row, and it stops, I need Copy the tag where it found row, and go to the next X in same row, after all rows is done it shall go to next row do the same.
Sub test()
Dim rng As Range
Dim cel As Range
Dim lastRow As Long
Dim writeRow As Long
Dim rCell As Range
Dim lColor, ColorRow As Long
Dim rColored As Range
Dim i, j As Integer
Dim temprow As Long
Dim lnRow As Long, cellvalueTemp As String
Dim WS As Workbook
lColor = RGB(255, 153, 204)
Set rColored = Nothing
Sheets.Add(After:=Sheets(Sheets.Count)).Name = "Sheet2"
Sheets.Add(After:=Sheets(Sheets.Count)).Name = "Sheet3"
Sheets("Sheet2").Cells(1, 1).Value = "Tag"
Sheets("Sheet2").Cells(1, 2).Value = "Terminal"
Sheets("Sheet2").Cells(1, 3).Value = "CollectiveGroupName"
Sheets("Sheet2").Cells(1, 4).Value = "LogicalGroupName"
lastRow = Sheets("Sheet1").Cells(Rows.Count, "A").End(xlUp).Row
writeRow = Sheets("Sheet2").Cells(Rows.Count, "A").End(xlUp).Row + 1
Set rng = Sheets("Sheet1").Range("A6:A" & lastRow)
For Each cel In rng
If cel.Interior.Color = lColor Then
ColorRow = cel.Row + 1
For i = ColorRow To lastRow
For j = 20 To 100 'Needs to be adjusted, possibily find the last colum and first
If Sheet1.Cells(i, j).Value = "X" Then
Sheets("Sheet2").Range("A" & writeRow).Value = Sheet1.Cells(i, 1).Value
Sheets("Sheet2").Range("B" & writeRow).Value = Sheet1.Cells(i - 7 - (i - ColorRow), j).Value
Sheets("Sheet2").Range("D" & writeRow).Value = Sheet1.Cells(i - 6 - (i - ColorRow), j).Value
writeRow = writeRow + 1
Columns("A:D").EntireColumn.AutoFit
End If
'Ikke gjør noe
Next j
Next i
If rColored Is Nothing Then
Else
'Ikke gjør noe
End If
End If
Next cel
End Sub

retrieve values from predefined row and a column range

How to retrieve values from predefined row and a column range (Incremental) to text boxes (Incremental) such that for example value of cell “J4” populate in "textbox1" and its column heading in "Label1" , value of cell “k4” populate in "textbox2" and its column heading in "Label2" and so on ............. value of cell“BG4” populate in "textbox50" and its column heading in "Label50".
I have tried the followings
Private Sub CommandButton1_Click()
Dim i As Long, lastrow As Long
Dim ws As Worksheet
Dim fcolumn As Long
Dim lcolumn As Long
Set ws = Worksheets("md")
lastrow = ws.Cells.Find(What:="*",
SearchOrder:=xlRows,SearchDirection:=xlPrevious, LookIn:=xlValues).Row + 1
fcolumn = 9
lcolumn = 50
For i = 2 To lastrow
fcolumn = fcolumn + 1
If ws.Cells(i, "A").Value = Val(Me.TextBox_orderno) Then
If Sheets("md").Cells(i, fcolumn).Value <> 0 Then
Me.Label1 = ws.Cells(2, fcolumn)
Me.TextBox1 = Sheets("md").Cells(i, fcolumn).Value
End If
If Sheets("md").Cells(i, fcolumn).Value <> 0 Then
Me.Label2 = ws.Cells(2, fcolumn)
Me.TextBox1 = Sheets("md").Cells(i, fcolumn).Value
End If
Next
End Sub
I'm still not sure exactly what you are doing, but see if this helps you along. It should at least show you how to dynamically refer to the names of controls which alter only in the number at the end.
Private Sub CommandButton1_Click()
Dim i As Long, lastrow As Long
Dim ws As Worksheet
Dim fcolumn As Long
Dim lcolumn As Long
Set ws = Worksheets("md")
lastrow = ws.Cells.Find(What:="*", SearchOrder:=xlRows, SearchDirection:=xlPrevious, LookIn:=xlValues).Row + 1
fcolumn = 9
lcolumn = 50
For i = 2 To lastrow
fcolumn = fcolumn + 1
If ws.Cells(i, "A").Value = Val(Me.Controls("TextBox" & i - 1)) Then
If Sheets("md").Cells(i, fcolumn).Value <> 0 Then
Me.Controls("Label" & i - 1).Value = ws.Cells(2, fcolumn)
Me.Controls("Textbox" & i - 1).Value = Sheets("md").Cells(i, fcolumn).Value
End If
End If
Next
End Sub

Resources