Extracting Data from Rows using a Macro(s)

A17BPG

New Member
Joined
Oct 4, 2016
Messages
20
Below is sample of what my spreadsheet may look like:
[TABLE="class: cms_table, width: 30"]
<tbody>[TR]
[TD]Name[/TD]
[TD]Tel.#[/TD]
[TD]PoultryReq[/TD]
[TD]Wght.[/TD]
[TD]PorkReq.[/TD]
[TD]Wght.[/TD]
[TD]BeefReq.[/TD]
[TD]Wght.[/TD]
[TD]Bacon[/TD]
[TD]Wght.[/TD]
[/TR]
[TR]
[TD]Fred[/TD]
[TD]123[/TD]
[TD]Turkey[/TD]
[TD]10.00[/TD]
[TD][/TD]
[TD][/TD]
[TD]Roasting[/TD]
[TD]3.00[/TD]
[TD]Back[/TD]
[TD]1.50[/TD]
[/TR]
[TR]
[TD]George[/TD]
[TD]456[/TD]
[TD][/TD]
[TD][/TD]
[TD]Leg[/TD]
[TD]4.00[/TD]
[TD][/TD]
[TD][/TD]
[TD]Gammon[/TD]
[TD]4.00[/TD]
[/TR]
[TR]
[TD]Arnold[/TD]
[TD]789[/TD]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[TD]Steak[/TD]
[TD]2.00[/TD]
[TD]Streaky[/TD]
[TD]1.00[/TD]
[/TR]
</tbody>[/TABLE]

What I want to do is get data from rows to generate an invoice listing only the data held in rows and ignoring all the empty cells. The results being passed to new sheet called invoice and listed as below, my original sheet has 54 columns and possibly up to 1000 rows so would want to go through list one row at a time and the print one invoice at a time.[TABLE="class: cms_table, width: 20"]
<tbody>[TR]
[TD]Name[/TD]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[/TR]
[TR]
[TD]Fred[/TD]
[TD][/TD]
[TD]Turkey[/TD]
[TD]10.00[/TD]
[TD]@1.20[/TD]
[TD]12.00[/TD]
[/TR]
[TR]
[TD][/TD]
[TD][/TD]
[TD]Roasting[/TD]
[TD]3.00[/TD]
[TD]@4.50[/TD]
[TD]13.50[/TD]
[/TR]
[TR]
[TD][/TD]
[TD][/TD]
[TD]Back[/TD]
[TD]1.50[/TD]
[TD]@2.50[/TD]
[TD]3.70[/TD]
[/TR]
[TR]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[/TR]
[TR]
[TD][/TD]
[TD][/TD]
[TD]Invoice[/TD]
[TD]Total[/TD]
[TD][/TD]
[TD]29.20[/TD]
[/TR]
</tbody>[/TABLE]

Thanks
 

Excel Facts

Spell Check in Excel
Press F7 to start spell check in Excel. Be careful, by default, Excel does not check Capitalized Werds (whoops)
Hello, I'll need some additional information before I can get you a full solution. What the cell addresses where your information is stored? Specifically, in your original table, is "Name" in cell A1, "Tel.#" in cell B1, and so on? Does the same apply to the second table, just on a different tab? Also, where are the prices coming from? Doing what you are asking about is definitely possible, but I need to know more before I'll be able to help you completely.
 
Upvote 0
This is a partial solution I was able to come up with. I've made some assumptions on the location of the cells. However, without knowing where the unit prices are, this code just puts 0 in for the cost of each item. I've left some comments where you can edit this to put in some cost retrieval code if you'd like to try that yourself.


Code:
Sub GenerateInvoices()
    Dim wsList As Worksheet, wsTemplate As Worksheet, Customer As Range, OrderRange As Range, Order As Range, Cost As Double
    
    Set wsList = Sheets("Sheet1") [COLOR=#008000]'Change the name here to be the name of the actual sheet with the list of who bought from you.[/COLOR]
    Set wsTemplate = Sheets("Invoice Template") [COLOR=#008000]'This may be changed if you want the tab to be named something other than "Invoice Template".[/COLOR]
    
    For Each Customer In Range(wsList.Cells(2, "A"), wsList.Cells(Rows.Count, "A").End(xlUp))
        wsTemplate.Cells(2, "A") = Customer
        Set OrderRange = Range(wsList.Cells(Customer.Row, "C"), wsList.Cells(Customer.Row, Columns.Count).End(xlToLeft))
        
        For Each Order In OrderRange
            If Order <> "" And IsNumeric(Order) = False Then
[COLOR=#008000]                'Insert cost retrieval code here, this could be a function if the code to do this ends up being more complex than just a line or two.[/COLOR]
[COLOR=#008000]                'Cost = ...[/COLOR]
                With wsTemplate.Cells(Rows.Count, "C").End(xlUp).Offset(1)
                    .Value = Order
                    .Offset(, 1) = Order.Offset(, 1)
                    .Offset(, 2) = Cost
                    .Offset(, 3) = .Offset(, 1) * Cost
                End With
            End If
        Next Order
        
        With wsTemplate.Cells(Rows.Count, "C").End(xlUp).Offset(2)
            .Value = "Invoice"
            .Offset(, 1) = "Total"
            .Offset(, 3) = WorksheetFunction.Sum(Range(wsTemplate.Cells(2, "F"), wsTemplate.Cells(Rows.Count, "F").End(xlUp)))
        End With
        
        wsTemplate.PrintOut
        wsTemplate.UsedRange.Offset(1).ClearContents
    Next Customer
End Sub
 
Upvote 0
Hi yes the Name, Tel.# etc. are along the top of sheet, as you ask A1,B1, C1 etc.There is "Price per Kilo" column after each "wght" column sorry I did not show these as short on space. Reference the second Tab "Invoice" I would like to present the data retrieved as you would / might find in a normal Invoice i.e. Customer # then Customers Name. Then below first item purchased then "wght" , "price per kilo" then a calculated field to give price of item. Then the following line the same for the next item purchased, finally at the end a calculated field to give a grand total of the invoice. As this system will be for a butchers at the moment VAT Tax is not involved so a Tax field would not be required, maybe later this could be added if needed. Many Thanks Brian
 
Upvote 0
I believe this code will work based on where the unit price is. If you want to add a Customer #, then I would also need to know where that is in the original sheet, as well as where you want it to go in the Invoice template. When you're working code, it's very important to be as detailed as possible about where information is and where you want it to go.

Code:
Sub GenerateInvoices()
    Dim wsList As Worksheet, wsTemplate As Worksheet, Customer As Range, OrderRange As Range, Order As Range
    
    Set wsList = Sheets("Sheet1")
    Set wsTemplate = Sheets("Invoice Template")
    
    For Each Customer In Range(wsList.Cells(2, "A"), wsList.Cells(Rows.Count, "A").End(xlUp))
        wsTemplate.Cells(2, "A") = Customer
        Set OrderRange = Range(wsList.Cells(Customer.Row, "C"), wsList.Cells(Customer.Row, Columns.Count).End(xlToLeft))
        
        For Each Order In OrderRange
            If Order <> "" And IsNumeric(Order) = False Then
                With wsTemplate.Cells(Rows.Count, "C").End(xlUp).Offset(1)
                    .Value = Order
                    .Offset(, 1) = Order.Offset(, 1)
                    .Offset(, 2) = Order.Offset(, 2)
                    .Offset(, 3) = .Offset(, 1) * .Offset(, 2)
                End With
            End If
        Next Order
        
        With wsTemplate.Cells(Rows.Count, "C").End(xlUp).Offset(2)
            .Value = "Invoice"
            .Offset(, 1) = "Total"
            .Offset(, 3) = WorksheetFunction.Sum(Range(wsTemplate.Cells(2, "F"), wsTemplate.Cells(Rows.Count, "F").End(xlUp)))
        End With
        
        With wsTemplate
            .Columns.AutoFit
            .PrintOut
            .UsedRange.Offset(1).ClearContents
        End With
    Next Customer
End Sub
 
Upvote 0
[TABLE="width: 50"]
<tbody>[TR]
[TD]Cust.#[/TD]
[TD]Cust.Name[/TD]
[TD]Tel.#[/TD]
[TD]Poultry [/TD]
[TD]Wght.[/TD]
[TD]Cost[/TD]
[TD]Beef[/TD]
[TD]Wght[/TD]
[TD]Cost[/TD]
[TD][/TD]
[/TR]
[TR]
[TD]1[/TD]
[TD]Fred[/TD]
[TD]123[/TD]
[TD]Turkey[/TD]
[TD]10.00[/TD]
[TD]11.00[/TD]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[/TR]
[TR]
[TD]2[/TD]
[TD]George[/TD]
[TD]456[/TD]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[TD]T.side[/TD]
[TD]3.00[/TD]
[TD]6.00[/TD]
[TD][/TD]
[/TR]
[TR]
[TD]3[/TD]
[TD]Brian [/TD]
[TD]789[/TD]
[TD]Chicken[/TD]
[TD]3.50[/TD]
[TD]8.00[/TD]
[TD]S.loin[/TD]
[TD]2.50[/TD]
[TD]12.00[/TD]
[TD][/TD]
[/TR]
[TR]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[/TR]
[TR]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[/TR]
</tbody>[/TABLE]
Hi Veritan I am on a very nice relaxing holiday at the moment and I am using my iPad to communicate with you so will try the code this weekend when home. Reference the question of the customer Number this is the first field i.e. A1. The Invoice layout should hopefully look something like below with the Cust.# being on the left followed by Cust. Name then below line by line the purchases that have been made again calculated field for each item and the total calculated field at bottom of invoice.
[TABLE="width: 50"]
<tbody>[TR]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[TD]Invoice[/TD]
[TD][/TD]
[/TR]
[TR]
[TD]3[/TD]
[TD]Brian [/TD]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[/TR]
[TR]
[TD][/TD]
[TD]Item[/TD]
[TD]Wght[/TD]
[TD]Cost[/TD]
[TD]Total[/TD]
[/TR]
[TR]
[TD][/TD]
[TD]Chicken[/TD]
[TD]3.50[/TD]
[TD]8.00[/TD]
[TD]28.00[/TD]
[/TR]
[TR]
[TD][/TD]
[TD]S.loin[/TD]
[TD]2.50[/TD]
[TD]12.00[/TD]
[TD]30.00[/TD]
[/TR]
[TR]
[TD][/TD]
[TD][/TD]
[TD][/TD]
[TD]G.Total[/TD]
[TD]58.00[/TD]
[/TR]
</tbody>[/TABLE]

Thanks Brian
 
Upvote 0
Okay, I think this is what you are looking for. Note that on the Invoice Template tab, I have the headers Item, Wght, Cost, and Total in Row 4, starting in Column B (make sure to put them in and format them however you want before you run the code). The word "Invoice" is already in the template and formatted however you want it to appear. At the very top of the code, I declare a constant that holds the currency number format. I'm using USD, so you'll probably want to change the sign to be whatever currency you're using. See if this works for you.

Code:
Const localCurrency As String = "$#,##0.00"
Sub GenerateInvoices()
    Dim wsList As Worksheet, wsTemplate As Worksheet, Customer As Range, OrderRange As Range, Order As Range


    Set wsList = Sheets("Sheet1")
    Set wsTemplate = Sheets("Invoice Template")
    
    For Each Customer In Range(wsList.Cells(2, "B"), wsList.Cells(Rows.Count, "B").End(xlUp))
        wsTemplate.Cells(3, "A") = Customer.Offset(, -1)
        wsTemplate.Cells(3, "B") = Customer
        Set OrderRange = Range(wsList.Cells(Customer.Row, "D"), wsList.Cells(Customer.Row, Columns.Count).End(xlToLeft))
        
        For Each Order In OrderRange
            If Order <> "" And IsNumeric(Order) = False Then
                With wsTemplate.Cells(Rows.Count, "B").End(xlUp).Offset(1)
                    .Value = Order
                    .Offset(, 1) = Order.Offset(, 1)
                    .Offset(, 1).NumberFormat = "0.00"
                    .Offset(, 2) = Order.Offset(, 2)
                    .Offset(, 2).NumberFormat = localCurrency
                    .Offset(, 3) = .Offset(, 1) * .Offset(, 2)
                End With
            End If
        Next Order
        
        With wsTemplate.Cells(Rows.Count, "D").End(xlUp).Offset(2)
            .Offset(, 1) = WorksheetFunction.Sum(Range(wsTemplate.Cells(2, "E"), wsTemplate.Cells(Rows.Count, "E").End(xlUp)))
            Range(wsTemplate.Cells(5, "E"), wsTemplate.Cells(Rows.Count, "E").End(xlUp)).NumberFormat = localCurrency
            .Offset(, 1).Borders(xlEdgeBottom).LineStyle = xlDouble
            wsTemplate.Columns.AutoFit
            .Value = "Invoice Total"
            .HorizontalAlignment = xlRight
        End With
        
        With wsTemplate
            .PrintOut
            With Union(.UsedRange.Offset(4), .Cells(3, "A").Resize(1, 2))
                .ClearFormats
                .ClearContents
            End With
        End With
    Next Customer
End Sub
 
Upvote 0
Hi Veritan,
Tried Macro out when home but unfortunately got an error box also it did not produce the display I would like.
I have saved a file in excel showing results from macro also an Order Entry Sheet and an Invoice Layout I would like to try to achieve, but I do not know if or how to attach a file to this reply.
If it is not possible to attach a file to this reply perhaps I could email you it.

Many Thanks
Brian
 
Upvote 0

Forum statistics

Threads
1,224,823
Messages
6,181,181
Members
453,022
Latest member
Mohamed Magdi Tawfiq Emam

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top