I need some help with my macros. The idea of this code is that I have one worksheet with big data about clients and multiple sheets which names are salesman's names. I want to copy and paste information about clients based on their salesman. In those salesman worksheet I have two places where I want to paste all clients: from 10th row in each worksheet I want to paste clients according to this condition If ws.Cells(i, "L").Value = salesmanName And ws.Cells(i, "I").Value = "valid". From 39 row in each worksheet I want to paste all clients with this condition ElseIf ws.Cells(i, "L").Value = salesmanName And Not ws.Cells(i, "I").Value = "valid" Then. Now with my code I get all clients of salesman from row 39 in each worksheet, maybe some of you will be able to help me to fix this problem.
Sub ExtractClientsBySalesman()
' Declare variables for the worksheet and last row of data
Dim ws As Worksheet
Dim lastRow As Long
Dim wsMatch As Worksheet
' Set the worksheet variable
Set ws = ThisWorkbook.Sheets("data")
' Find the last row of data in the "data" worksheet
lastRow = ws.Cells(ws.Rows.Count, "D").End(xlUp).Row
' Loop through the data in column "D" (client)
For i = 2 To lastRow
' Check if the value in column "salesman" (column "E") matches "name_surname"
For Each wsMatch In ThisWorkbook.Sheets
Dim pasteRow As Long
Dim pasteRow2 As Long
pasteRow = 10
pasteRow2 = 39
salesmanName = wsMatch.Range("A5").Value
If ws.Cells(i, "L").Value = salesmanName And ws.Cells(i, "I").Value = "valid" Then
' Copy the client information to the new worksheet
pasteRow = wsMatch.Cells(wsMatch.Rows.Count, "A").End(xlUp).Row + 1
' Copy the client information to the worksheet
wsMatch.Cells(pasteRow, 1).Value = ws.Cells(i, 1).Value
wsMatch.Cells(pasteRow, 2).Value = ws.Cells(i, 9).Value
wsMatch.Cells(pasteRow, 3).Value = ws.Cells(i, 42).Value
wsMatch.Cells(pasteRow, 4).Value = ws.Cells(i, 4).Value
wsMatch.Cells(pasteRow, 5).Value = ws.Cells(i, 14).Value
wsMatch.Cells(pasteRow, 6).Value = ws.Cells(i, 16).Value
wsMatch.Cells(pasteRow, 7).Value = ws.Cells(i, 40).Value
wsMatch.Cells(pasteRow, 8).Value = ws.Cells(i, 12).Value
ElseIf ws.Cells(i, "L").Value = salesmanName And Not ws.Cells(i, "I").Value = "valid" Then
pasteRow2 = wsMatch.Cells(wsMatch.Rows.Count, "A").End(xlUp).Row + 1
' Copy the client information to the worksheet
wsMatch.Cells(pasteRow2, 1).Value = ws.Cells(i, 1).Value
wsMatch.Cells(pasteRow2, 2).Value = ws.Cells(i, 9).Value
wsMatch.Cells(pasteRow2, 3).Value = ws.Cells(i, 42).Value
wsMatch.Cells(pasteRow2, 4).Value = ws.Cells(i, 4).Value
wsMatch.Cells(pasteRow2, 5).Value = ws.Cells(i, 14).Value
wsMatch.Cells(pasteRow2, 6).Value = ws.Cells(i, 16).Value
wsMatch.Cells(pasteRow2, 7).Value = ws.Cells(i, 40).Value
wsMatch.Cells(pasteRow2, 8).Value = ws.Cells(i, 12).Value
End If
Next wsMatch
Next i
End Sub
1) It's better deal with next available line with different code. It's easier!
2) Also it's healthier that you exclude data worksheet from salesman worksheets.
3) It is advisable to use the Option Explicit clause to force to declare variables explicitly.
Option Explicit
Sub ExtractClientsBySalesman()
' Declare variables for the worksheet and last row of data
Dim ws As Worksheet
Dim lastRow As Long
Dim wsMatch As Worksheet
Dim valid As Boolean
Dim lPaste As Long
Dim i As Integer
Dim salesmanName As String
' Initial line for each condition
Dim pasteRow As Long
Dim pasteRow2 As Long
pasteRow = 10
pasteRow2 = 39
' Set the worksheet variable
Set ws = ThisWorkbook.Sheets("data")
' Find the last row of data in the "data" worksheet
lastRow = ws.Cells(ws.Rows.Count, "D").End(xlUp).Row
' Loop through the data in column "D" (client)
For i = 2 To lastRow
' column "salesman" (column "E") matches "name_surname"?
For Each wsMatch In ThisWorkbook.Sheets
If wsMatch.Name <> "data" Then
salesmanName = wsMatch.Range("A5").Value
lPaste = 0
If ws.Cells(i, "L").Value = salesmanName Then
valid = ws.Cells(i, "I").Value = "valid"
If valid Then
' 1st section between lines 10 and 37.
' Line 38 is 2nd section header
lPaste = pasteRow2 - 2
' 1st section after line 37 is invalid!
If Not IsEmpty(wsMatch.Cells(lPaste, 1).Value) Then
MsgBox ("Data overflow at first section")
End ' Exit from program
End If
' 1st available line between 10 and 37
lPaste = wsMatch.Cells(lPaste, 1).End(xlUp).Row
lPaste = Application.Max(pasteRow, lPaste + 1)
Else
' 1st available line after line 39
lPaste = wsMatch.Cells(Cells.Rows.Count, 1).End(xlUp).Row
lPaste = Application.Max(pasteRow2, lPaste + 1)
End If
End If ' Same salesman
' Copy the client information to the new worksheet
If (lPaste > 0) Then ' Same Salesman
wsMatch.Cells(lPaste, 1).Value = ws.Cells(i, 1).Value
wsMatch.Cells(lPaste, 2).Value = ws.Cells(i, 9).Value
wsMatch.Cells(lPaste, 3).Value = ws.Cells(i, 42).Value
wsMatch.Cells(lPaste, 4).Value = ws.Cells(i, 4).Value
wsMatch.Cells(lPaste, 5).Value = ws.Cells(i, 14).Value
wsMatch.Cells(lPaste, 6).Value = ws.Cells(i, 16).Value
wsMatch.Cells(lPaste, 7).Value = ws.Cells(i, 40).Value
wsMatch.Cells(lPaste, 8).Value = ws.Cells(i, 12).Value
End If ' Same Salesman
End If ' Other workshets than 'data'
Next wsMatch
Next i
End Sub
Not tested because there is no data example, but my guess is that first time you got ws.Cells(i, "I").Value = "valid" it should go to row 10 and from now on row 11, 12 and so on.
Same for Not ws.Cells(i, "I").Value = "valid": first match should go to 39 and then later to 40, 41 and so on.
If cells A9 and A38 are headers row and they are not empty you could try this:
Replace pasteRow = wsMatch.Cells(wsMatch.Rows.Count, "A").End(xlUp).Row + 1
with pasteRow = wsMatch.Range("A38").End(xlUp).Row + 1
Your code does not work properly because if there is something in A38, when you do pasteRow = wsMatch.Cells(wsMatch.Rows.Count, "A").End(xlUp).Row + 1 it will stop at row 38 and that would explain why you got everything into A39.
It's quite difficult for me because I don't see the data and the expected result in some sheets. Anyway this is not directly the answer to your question, but my guess is something like this :
Table in sheets "DATA" is something like this:
Another sheets (sheet2 to sheet4) is something like this :
Expected result is something like this :
In short, to each sheets other than sheet DATA, get the name value in cell A5, then get range of cells in column L sheet DATA which contains that name. Within this range.offset(0,-3) ---> (column I), to each cell with "Valid" value row Nth, fill the looped sheet (column A to C) start from row 7 with the value of column-1/column-17/column-7 row Nth. And to each cell with value is not "Valid" row Nth, fill the looped sheet (column A to C) start from row 20 with the value of column-1/column-17/column-7 row Nth.
Sub test()
Dim rg As Range: Dim arr: Dim sh
Dim cnt1 As Integer: Dim cnt2 As Integer: Dim i As Integer
Dim rgValid As Range: Dim rgNotValid As Range
With Sheets("DATA") 'change as needed
Set rg = .Range("L2", .Range("L2").End(xlDown)) 'change as needed
End With
arr = Array(1, 14, 7) 'change as needed
For Each sh In Sheets
If Not rg.Find(sh.Range("A5").Value) Is Nothing And sh.Name <> "DATA" Then
With rg
.Replace sh.Range("A5").Value, True, xlWhole, , False, , False, False
With .SpecialCells(xlConstants, xlLogical).Offset(0, -3)
cnt1 = Application.CountA(.Cells): cnt2 = Application.CountIf(.Cells, "Valid")
If cnt1 = cnt2 Then
Set rgValid = .Cells: Set rgNotValid = .End(xlDown)
ElseIf cnt2 = 0 Then
Set rgNotValid = .Cells: Set rgValid = .End(xlDown)
ElseIf cnt1 <> cnt2 And cnt2 <> 0 Then
.Replace "Valid", "", xlWhole, , False, , False, False
Set rgValid = .SpecialCells(xlBlanks): Set rgNotValid = .SpecialCells(xlConstants)
rgValid.Value = "Valid"
End If
End With
.Replace True, sh.Range("A5").Value, xlWhole, , False, , False, False
End With
Set rgValid = rgValid.Offset(0, -8)
Set rgNotValid = rgNotValid.Offset(0, -8)
For i = 1 To UBound(arr) - LBound(arr) + 1
rgValid.Offset(0, arr(i - 1) - 1).Copy Destination:=sh.Cells(7, i) 'change as needed
rgNotValid.Offset(0, arr(i - 1) - 1).Copy Destination:=sh.Cells(20, i) 'change as needed
Next
End If
Next
End Sub
rg is the range of name in sheet DATA column L. There must be no blank cell within this rg.
arr is an array variable with the expected column sequence number. In this example case, the sequence is : column A, column N and column G ---> 1,14,7. In your case, it will be : 1,9,42,4,14,16,40,12.
Then it loop to each sheet other than sheet DATA as sh variable, and get the name which resides in each looped sheet cell A5.
Then in sheet DATA column L, it get the range of cell.offset(0,-3), which value is that name. So, the range is column I (because offset 0,-3). Within this range in column I, it counts how many data are there as cnt1, and count how many data with words "Valid" as cnt2.
If cnt1 = cnt2 then it means in the range of that name, column I all have "Valid" value. So it create a range for all those Valid value as rgValid variable, and create a range which value is blank as rgNotValid variable.
If cnt2 = 0 then it means in the range for that name, column I doesn't have a "Valid" value at all. So it create a range for all those not Valid value as rgNotValid variable, and create a range which value is blank as rgValid variable.
if cnt1 <> cnt2 and cnt2 <> 0 then it means some value within the range for that name has "Valid" value, some not. So it create a range for all those Valid value as rgValid variable, and create a range which value is not "Valid" as rgNotValid variable.
Finally it loop as many as the item in arr to put the expected value to each looped sheet column A to C starting from row 7 for the Valid value, starting from row 20 for the not Valid value.
Please note, the code assumes that in sheet DATA column I and column L, there'll be no blank cell in between row of data.
I have a sheet1 data in below format
I need VBA Code to vlookup in sheet2 on Group Id and Product ID in sheet1 and insert new row highlighted in yellow called BT order and populate 400 and 600 values from DMD column against Wk8 and Wk9 column which is vlookup value of week Num from second sheet.
Dim i As Long
For i = 2 To Range("E" & Rows.Count).End(xlUp).Row
If Trim(Range("E" & i).Value) = RTrim("CMT") Then
Rows(i + 1).Insert shift:=xlShiftDown
Range("A" & i + 1 & ":D" & i + 1).Value = Range("A" & i - 1 & ":D" & i - 1).Value
Range("E" & i + 1).Value = "BT/Order"
End If
Next i
Try this:
Sub Tester()
Dim ws1 As Worksheet, ws2 As Worksheet
Dim i As Long, i2 As Long, grp, prod, amt, wk
Set ws1 = ThisWorkbook.Worksheets("Sheet1")
Set ws2 = ThisWorkbook.Worksheets("Sheet2")
i = 2
Do While i <= ws1.Cells(Rows.Count, "E").End(xlUp).Row
If Trim(ws1.Range("E" & i).Value) = RTrim("CMT") Then
ws1.Rows(i + 1).Insert shift:=xlShiftDown
ws1.Cells(i + 1, "A").Resize(1, 4).Value = ws1.Cells(i, "A").Resize(1, 4).Value
ws1.Cells(i + 1, "E").Value = "BT/Order"
'current group/product id's
grp = ws1.Cells(i, "A").Value
prod = ws1.Cells(i, "C").Value
'loop sheet2 and find matches
For i2 = 2 To ws2.Cells(Rows.Count, 1).End(xlUp).Row
If ws2.Cells(i2, "A").Value = grp Then
If ws2.Cells(i2, "B").Value = prod Then
'got match - check amount and week
amt = ws2.Cells(i2, "D").Value
wk = ws2.Cells(i2, "E").Value
If amt > 0 Then
'insert amount in relevant column
ws1.Cells(i + 1, "F").Offset(0, wk).Value = amt
End If
End If
End If
Next i2
End If
i = i + 1
Loop
End Sub
i have a array "v" in sheet 3 and i need to copy the last column of it to sheet one using a loop.it is only working if i am on sheet 3. i want it to work regardless of what sheet i am on. In this loop i have
For i = 1 To Cells(12, 8).Value 'this cell is in sheet 2
'i need this Cells(7, i + 8).Value output to be in sheet 1
Cells(7, i + 8).Value = v(i, UBound(v, 1))
Next i
' for the array
With Worksheets("three")
Const firstCol As Long = 7, firstRow As Long = 12
lastCol = Sheet3.Cells(firstRow, Columns.Count).End(xlToLeft).Column
lastRow = Sheet3.Cells(Rows.Count, lastCol).End(xlUp).Row
v= Range(Cells(firstRow, firstCol), Cells(lastRow, lastCol))
End With
braX
This should get it done:
Dim Src as Worksheet
Dim Dst as Worksheet
Set Dst = Worksheets("One") 'I assume this isn't the real name?
Set Src = Worksheets("Three") 'I assume this isn't the real name?
'You'll progablly want to dim/set this sheet also but I don't know what to call it
For i = 1 To Worksheets("Sheet2").Cells(12, 8).Value 'this cell is in sheet 2
'i need this Cells(7, i + 8).Value output to be in sheet 1
Dst.Cells(7, i + 8).Value = v(i, UBound(v, 1))
Next i
' for the array
With Src
Const firstCol As Long = 7, firstRow As Long = 12
lastCol = .Cells(firstRow, Columns.Count).End(xlToLeft).Column
lastRow = .Cells(Rows.Count, lastCol).End(xlUp).Row
'*** Don't know which sheet formula below is looking at but you get the gist
v= Range(Cells(firstRow, firstCol), Cells(lastRow, lastCol))
End With 'Src
HTH
Basically I am making a Userform and would like that the data start on the next emptyrow in Column B starting from Cell B4.
Here is the code I got from a userform template found online:
Private Sub OKButton_Click()
Dim emptyRow As Long
'Make Sheet1 active
Sheet1.Activate
'Determine emptyRow
emptyRow = WorksheetFunction.CountA(Range("A:A")) + 2
'Transfer information
Cells(emptyRow, 1).Value = NameTextBox.Value
Cells(emptyRow, 2).Value = PositionTextBox.Value
Cells(emptyRow, 3).Value = EmployeeIDTextBox.Value
Thanks for the assistance.
Private Sub OKButton_Click()
' Declare/Set variable for referencing workbook
Dim wb As Workbook
Set wb = ThisWorkbook
' Declare/Set variable for referencing worksheet
Dim ws As Worksheet
Set ws = wb.Worksheets("Sheet1")
'Determine next empty Row
Dim emptyRow As Long
' Code below works like this:
' ws = the worksheet
' .Range("b65536") is the last cell in column b
' .End(xlUp) means go up from cell b65536 until we hit a non-empty cell
' .Row is the row number of that non-empty cell
' + 1 to get to the empty row below
emptyRow = ws.Range("b65536").End(xlUp).Row + 1
' Create/Set a variable for referencing the range we want to use
' The range will be set to start at column b of
' the empty row and go to column AF of the empty row
Dim rng As Range
Set rng = ws.Range("b" & emptyRow & ":AF" & emptyRow)
'Transfer information
' If we didn't use "With rng", below, you'd have to write each of these lines like:
' rng.Cells(...
' Since the range is only 1 row, you can replace the .Cells(emptyrow, 1), etc.
' like you had and just do .Cells(1,1), etc.
With rng
.Cells(1, 1).Value = NameTextBox.Value
.Cells(1, 2).Value = PositionTextBox.Value
.Cells(1, 3).Value = EmployeeIDTextBox.Value
.Cells(1, 4).Value = GenderComboBox.Value
.Cells(1, 5).Value = NationalityTextBox.Value
.Cells(1, 6).Value = DOBTextBox.Value
.Cells(1, 7).Value = PassportTextBox.Value
.Cells(1, 8).Value = PassportExpTextBox.Value
.Cells(1, 9).Value = MedicalTextBox.Value
.Cells(1, 10).Value = YFTextBox.Value
.Cells(1, 11).Value = Lic1TextBox.Value
.Cells(1, 12).Value = Lic1FlagTextBox.Value
.Cells(1, 13).Value = Lic1ExpTextBox.Value
.Cells(1, 14).Value = Lic2TextBox.Value
.Cells(1, 15).Value = Lic2FlagTextBox.Value
.Cells(1, 16).Value = Lic2ExpTextBox.Value
.Cells(1, 17).Value = DPComboBox.Value
.Cells(1, 18).Value = DPCertTextBox.Value
.Cells(1, 19).Value = DPCertExpTextBox.Value
.Cells(1, 20).Value = GMDSSTextBox.Value
.Cells(1, 21).Value = GMDSSCertTextBox.Value
.Cells(1, 22).Value = GMDSSExpTextBox.Value
If RadarCheckBox.Value = True Then .Cells(1, 23).Value = "Yes"
If ArpaCheckBox.Value = True Then .Cells(1, 24).Value = "Yes"
If EcdisCheckBox.Value = True Then .Cells(1, 25).Value = "Yes"
If BosietCheckBox.Value = True Then .Cells(1, 26).Value = "Yes"
If HuetCheckBox.Value = True Then .Cells(1, 27).Value = "Yes"
If HloCheckBox.Value = True Then .Cells(1, 28).Value = "Yes"
If OrbCheckBox.Value = True Then .Cells(1, 29).Value = "Yes"
If EACheckBox.Value = True Then .Cells(1, 30).Value = "Yes"
If VsoOptionButton1.Value = True Then
.Cells(1, 31).Value = "Yes"
Else
.Cells(1, 31).Value = "No"
End If
End With
End Sub
enter image description hereThere are 2 sheets, Sheet1 and Sheet2.
Sheet1 contain 10 columns and 5 rows with data including blank.
The requirement is to copy the data from Sheet 1 and to put in another sheet Sheet 2, wherein only populate the cell which is not blank.
I get the run time error 1004 - Application or object defined error.
The code snippet is:-
Set wsht1 = ThisWorkbook.Worksheets("Sheet1")
Set wsht2 = Sheets("Sheet2")
finalrow = wsht1.Cells(wsht1.Rows.Count, 1).End(xlUp).Row
For i = 1 To finalrow
If wsht1.Cells(i, 1).Value <> " " Then
Range(Cells(i, 2), Cells(i, 2)).Copy
Worksheets("Sheet2").Select
wsht2.Range(Cells(1, i)).PasteSpecial Paste:=xlPasteFormats
End If
Next i
Can u help me in sorting this out?
You cannot define a range like that:
wsht2.Range(Cells(1, i))
you might use:
wsht2.Cells(1, i).PasteSpecial Paste:=xlPasteFormats
BTW: with this code you won't find empty cells:
If wsht1.Cells(i, 1).Value <> " " Then
you should use:
If wsht1.Cells(i, 1).Value <> "" Then
(the difference is a missing space between the quotes)
if you want to copy the values only and to make it with a loop I'd do the following:
Sub copying()
Set wsht1 = ThisWorkbook.Worksheets("Sheet1")
Set wsht2 = Sheets("Sheet2")
finalrow = wsht1.Cells(wsht1.Rows.Count, 1).End(xlUp).Row
For i = 1 To finalrow
If wsht1.Cells(i, 1).Value <> "" Then
For j = 1 To 5
wsht2.Cells(i, j).Value = wsht1.Cells(i, j).Value
Next j
End If
Next i
End Sub
If you only have 5 cells with data in Sheet 1 and only want those 5 rows copying to Sheet 2 use the following, similar to Shai's answer above with an extra counter for the rows in Sheet 2.
Sub copying()
Set wsht1 = ThisWorkbook.Worksheets("Sheet1")
Set wsht2 = Sheets("Sheet2")
finalrow = wsht1.Cells(wsht1.Rows.Count, 1).End(xlUp).Row
k = 1
For i = 1 To finalrow
If wsht1.Cells(i, 1).Value <> "" Then
For j = 1 To 5
wsht2.Cells(k, j).Value = wsht1.Cells(i, j).Value
Next j
k = k + 1
End If
Next i
End Sub
EDIT
As per your comment if you want to dynamically change j replace For j = 1 To 5 with
For j = 1 To wsht1.Cells(i, Columns.Count).End(xlToLeft).Column
The code below will copy only values in Column A (non-empty cells) from Sheet 1 to Sheet2:
Dim j As Long
Set wsht1 = ThisWorkbook.Worksheets("Sheet1")
Set wsht2 = Sheets("Sheet2")
finalrow = wsht1.Cells(wsht1.Rows.Count, 1).End(xlUp).Row
j = 1
For i = 1 To finalrow
With wsht1
' if you compare to empty string, you need to remove the space inside the quotes
If .Cells(i, 1).Value <> "" And .Cells(i, 1).Value <> " " Then
.Cells(i, 1).Copy ' since you are copying a single cell, there's no need to use a Range
wsht2.Range("A" & j).PasteSpecial Paste:=xlPasteValues, Paste:=xlPasteFormats
j = j + 1
End If
End With
Next i