1

I need help to create an automatic method to copy a row to a specific sheet.

I have a Tab (Sales) with a WEB api query importing data in this sheet every 5 min. I have a row within the Sales sheet with a name range identifying each item. The row has 100 different names and there are 100 sheets created with same names within the workbook.

I want to copy the entire row for each item and copy it to the sheet with the same name of the item.

This is to fire off the copy sub:

'Copy Sales data Every 10 Min
Sub test()
    'Application.OnTime Now + TimeValue("00:10:00"), "my_Procedure…"
End Sub

I have seen many methods on how to copy the row automatically, but I need help in copy row and use the item name and paste to other sheet with same name.

YowE3K
  • 23,852
  • 7
  • 26
  • 40
Xango
  • 9
  • 4
  • I feel like i am missing something here. It reads to me like...For each refresh read the row in once to a variable. Then loop an array holding the named ranges and use that loop to set the target sheet name to paste too (same row number?) ? And i would read the named ranges in from a range in a worksheet at the start. And throw in some error handling. – QHarr Dec 17 '17 at 08:44

1 Answers1

2

Without further information here is an outline of what i described in the comments. Here the list of named ranges starts at cell J3 in NamesSheet. In the image, i have shown it in the same sheet (SourceSheet for simplicity). The list is read into an array and that array is looped to select the appropriate sheet to set the values in.

Rather than copy and paste it sets the target row (the next available row), in the sheet accessed by the array index, equal to the source row (copyRow). A With statement is used to avoid selecting the target sheet (more efficient).

No error handling added for missing sheets at present.

I haven't assumed there will be a list of 100 named ranges in the sheet, otherwise you could have sized the array from the start.

Named ranges in ColA of Sales tab:

Named range in ColA of Sales tab

List of named ranges in Names sheet (abbreviated)

Names sheet holding list of named ranges that are in Sales tab

Option Explicit

Private Sub myProc()

Dim wb As Workbook
Dim wsSource As Worksheet
Dim wsNames As Worksheet

Set wb = ThisWorkbook
Set wsSource = wb.Worksheets("Sales")
Set wsNames = wb.Worksheets("Names")

Dim namesArr()
namesArr = wsNames.Range("J3:J" & wsNames.Cells(wsNames.Rows.Count, "J").End(xlUp).Row).Value

If UBound(namesArr, 1) <> wsSource.Range("ITEMName").Rows.Count Then
    MsgBox "There are not a matching number of named ranges listed in Names sheet."
    Exit Sub
End If

Dim i As Long
Dim currLastRow As Long
'Any optimization code could actually go in outer calling sub but consider
'some such as the following

Application.ScreenUpdating = False
Dim copyRow As Range

For i = LBound(namesArr, 1) To UBound(namesArr, 1)

   With wb.Worksheets(namesArr(i, 1))

     Set copyRow = wsSource.Range(namesArr(i, 1)).EntireRow

     If IsEmpty(.Range("A1")) Then   'First row in sheet is available

         .Rows(1).Value = copyRow.Value2

     Else

         currLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row

         .Rows(currLastRow + 1).Value = copyRow.Value2

     End If

   End With

Next i

Application.ScreenUpdating = True

End Sub

Version 2:

Looping Named Ranges in Sales sheet (assumes only 101 Named Ranges in the sheet, tested with workbook scope, and that you will ignore 1 of these which is called ITEMName, no list required in a different sheet. Approach adapted from @user1274820.

Option Explicit

Private Sub myProc2()

    Dim wb As Workbook
    Dim wsSource As Worksheet

    Set wb = ThisWorkbook
    Set wsSource = wb.Worksheets("Sales")

    Dim currLastRow As Long
    'Any optimization code could actually go in outer calling sub but consider
    'some such as the following

    Application.ScreenUpdating = False

    Dim copyRow As Range
    Dim nm As Variant

    For Each nm In ThisWorkbook.Names

        If nm.RefersToRange.Parent.Name = "Sales" And nm.Name <> "ITEMName" Then

            With wb.Worksheets(nm.Name)

                Set copyRow = wsSource.Range(nm.Name).EntireRow

                If IsEmpty(.Range("A1")) Then    'First row in sheet is available

                    .Rows(1).Value = copyRow.Value2

                Else

                    currLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row

                    .Rows(currLastRow + 1).Value = copyRow.Value2

                End If

            End With

        End If

    Next nm

    Application.ScreenUpdating = True

End Sub
QHarr
  • 83,427
  • 12
  • 54
  • 101
  • Thank you for a quick response. – Xango Dec 17 '17 at 14:30
  • Thank you for a quick response. Your code worked as designed. Allow me to elaborate my effort. I have a source sheet that has the data (to be copied per row) which will refresh for each item every 10 min. I have target sheets already created/named (ItemName1,2,3,4) based on Column's A (named range) "ItemName" from the source sheet. I am trying to update the target sheet with the source's sheet data per item after source sheet refreshes.i am looking to update the target sheet info on the next empty row – Xango Dec 17 '17 at 14:42
  • Explain a bit more about the per row? Are you actually copying the entire row or just the named range? Are all the named ranges in the same row? I have updated code to always find next available row. – QHarr Dec 17 '17 at 15:02
  • Thank you that worked. But the source row will need to be the ITEMNames Dim namesArr() namesArr = wsNames.Range("A2:A" & wsNames.Cells(wsNames.Rows.Count, "A").End(xlUp).Row).Value Dim copyRow As Range Set copyRow = wsSource.Rows(ITEMSnames) As it is right now i am getting row 5 as it identify in the source row line. Thank you – Xango Dec 17 '17 at 15:12
  • The ItmesNames are all in the same column A2:A100 (also a named range(ITEMName)) within the source sheet. Each itemName on the sourcesheet has a row which i would want to copy to another existing TAB/Sheet having the same name as the item. e.g. Item1,2,3,4 – Xango Dec 17 '17 at 15:27
  • Read column A with the named ranges into the array, the. Loop the array and access the named range row property to set the copy row? Is each named range one row in height? – QHarr Dec 17 '17 at 15:31
  • Is each named range one row in height? Yes,,, I am getting at et copyRow = wsSource.Range(namesArr(i, 1)).EntireRow Application-defined or object-defined error. At "With wb.Worksheets(namesArr(i, 1))" i see it passing the first itemname. – Xango Dec 17 '17 at 16:23
  • one thing i noticed, Set wb = ThisWorkbook Set wsSource = wb.Worksheets("Sales") Set wsNames = wb.Worksheets("Sales") I have to have it this way for the nameArr to carry the range. to your question of, MsgBox wsSource.Range(namesArr(i, 1)).EntireRow.Address before the Set copyRow = "Application-defined or object-defined error". – Xango Dec 18 '17 at 12:29
  • namesArr should be pointing at which ever range has the text list of your named ranges. – QHarr Dec 18 '17 at 13:34
  • Here are some things to check as this should be easy to solve: 1) In the named range A2:A100 called ITEMName, is each cell a named range e.g. is A2 named ItemName1? 2) In wsNames.Range("J3:J103" ) - do you have a list of the 100 named ranges i.e. ItemName1, ItemName2........? – QHarr Dec 19 '17 at 07:07
  • I have added additional image. If this doesn't work there is something different between your setup and mine that we need to pinpoint. Verify that the set up is the same using, for example, the suggestions in my comment above as a starter. – QHarr Dec 19 '17 at 07:19
  • Set wsNames = wb.Worksheets("Sales") is WRONG. You need a sheet with a LIST of the named ranges in. This is because i thought it easier to read the list into an array and loop this than have to loop all Named ranges in the sourcesheet (i was worried about their being more named ranges potentially than the 100 + 1 (overarching one)) – QHarr Dec 19 '17 at 07:26
  • This was because Set wsNames = wb.Worksheets("Sales") was WRONG for the code i gave. You need a sheet with a LIST of the named ranges in. This is because i thought it easier to read the list into an array and loop this than have to loop all Named ranges in the sourcesheet (i was worried about their being more named ranges potentially than the 100 + 1 (overarching one)) . However, i have now added a version 2 of the code where you can use the approach i think you are after. – QHarr Dec 19 '17 at 07:56
  • Ok Couple of thing i found out from your code and how i was explaning my workbook. 1st, i had 100 items all contained in 1 named range "ITEMNames" 2nd any of the item names in source column 1 cannot have special characters in the name nor could the sheets that were created from column A have special characters. besides that the code works well both methods. Thank you for your effort. If i would want to have 1 single named range for items 1-1500 in column A, would i have to change any of the code? – Xango Dec 20 '17 at 23:24
  • For the first version you will still need to have a separate named range that lists each of the individual named ranges. I will add a bit of code that checks that the # rows in ITEMNames = UBound(namesArr,1) and tells you if there is a difference. The second version will loop all named ranges in the Sales sheet and ignore only ITEMNames. Let me know if this works. – QHarr Dec 21 '17 at 06:03