Automate Invoices in Xero in 2025 (from Excel and Google Sheets) in 1 Click

In this tutorial Isaac from Opsa.co demonstrates how to instantly generate unlimited Xero invoices directly from a Google Sheet using the automation platform Make. He starts with a simple spreadsheet containing contact name, description, quantity, amount and a status column (not ready / ready / invoice). The first workflow searches rows marked "ready", creates a new contact (if needed), builds a single‑line‑item invoice, and updates the sheet status to "invoice" to prevent re‑processing. Isaac then shows a second version that adds a router module to "find‑or‑create" contacts, avoiding duplicate contacts when the same client appears multiple times. Finally, he presents a third, more advanced workflow that parses comma‑separated values in the description, quantity and amount columns, splits them into separate line‑item arrays, and aggregates them into the structure required by Xero to create multi‑item invoices. Throughout, he tests each scenario, verifies contacts and invoices in Xero, and notes that a similar use case can be built for QuickBooks using Zapier. The video ends with a call to stay efficient.
Chapters
Hey there, I'm Isaac from Opsa.co, and in this video I want to share how you can create as many invoices as you want instantly in Xero just from checking boxes in a spreadsheet. I'll share how you can do this in a simple tool called Make, how to handle when you have multiple items, and how to attach those invoices to the right contact in an automatic fashion. With that, let's get into it. So here I have Xero already created, and I want to quickly share with you what the other assets look like. So we have a Google Sheet that's pretty simple, just 5 columns with contact name, description. I should probably just call this descriptions just because we're going to do this with multiple line items in a second example. And I have status. In status, I have just like not ready, ready, and invoice. And you'll see why I do this is such that I can potentially trigger this I can manipulate or control when to trigger this properly. So just for the example here, let's just say Officer Life, and we have a particular service, and we have one of those services, and it's $100. Okay, let's say it's not ready for now. I don't want to trigger it just yet, but I'm going to go to Make and show you how I've done this particular simple example. Of creating the contact, creating the invoice, and updating the Google Sheets back again to show that it is done. So the way I've done this is I have a Google Sheets module, a step, a Google Sheets step that's searching for rows in that particular spreadsheet. And it's looking specifically when the status is ready and when the contact name exists. I have just a contact name exists as a buffer, if you like, Just to make sure that there's actually data available in this in the sheet. I could also make sure that the other columns have some data available if I wanted just to be safe. But for the sake of this example, I'd say this is enough. If I try to run this module, you realize this actually it's able to run step by step. I can test each step at a time, and here it's telling me, hey, I found nothing with your criteria. If I move this to ready. Though I should be able to come here and say run it again and let me see if you find what I have. And there it is. And we can see the contact name, the description, the quantity, and the amount. Perfect. Now I would create the invoice straight away if I could, but the challenge is that the invoice requires a contact ID. As a result, I have to make sure I create the contact first. So that's exactly what I do using the demo company I have here. I create the invoice now with the contact ID, and in the first item I have a description, the quantity, and the amount. It's worth noting that right now I just have one item mapped, but in the following examples we're gonna see an example— redundant words there— but we're gonna see an example how to actually create as many line items as you want in the spreadsheet. Last but not least, I want to make sure I update this to invoice because if I leave this as ready When this runs again, it's going to pick that invoice again and the system is going to break. So if I go to the contacts section of my demo company zero and I look for Opsor, we're going to probably see several Opsor contacts because I tested this in advance, but I haven't had an Opsor live version. So if I go ahead and run this, we should be able to see it creates a contact, it creates the invoice, and it Updates the spreadsheet. If I go to the spreadsheet, I should see now that this is invoice. Great. And I should see that the contact should now be here available in my contact list. And if I click on that contact, Ops or Life, I should be able to see an invoice for that quote unquote client. That's $100. And if I click on it, I should be able to see the detail. Oh, hey, here's the service. Description, here's the quantity, and here's the price. Looks like it categorizes into a particular account straight away because maybe there are other rules, but you could potentially manipulate that and have other items, have other accounts, have other quantities if you have that, if you map that differently in the spreadsheet, and potentially some of these other fields. But just to keep the example simple, we populated these through particular fields. Now you might wonder, well, this is actually creating the contact every time. But now this contact exists. So that's the second Zap I wanna run through you because this particular automation would actually break when the contact is already there. As you can see here, hey, I already have a contact. Or in this particular case, actually it broke because there's no contacts and there's nothing I have here. But let's just say I copied this and I want it now a different, you know, service number 2 that has 2 items and it's $50 and it's ready. I could try to map this and run this through this workflow, but it wouldn't work because Ops for Life, it's already assigned. It's, it already exists. So that's what I wanna share with you on version 2 of this workflow. In version 2 of this workflow, I've made sure to actually find the contact first so that if it doesn't exist, we create it. And if it exists, we simply create the invoice straight away. Because we found it. And the only change in this workflow is these filters, this module. It's called a router module that allows me to go into different paths based on different conditions, conditions which are included in this filter as I'll share. And now we're searching for the contact in advance. The invoice and the spreadsheet steps are exactly the same. Okay, so if we take a look, we can see that's ready. And as we saw earlier, but now I'm searching for the contact. Specifically, I'm looking for the contact name as a search term. And then what I'm doing is I have 2 paths. One is, did you find anything? And the way I have that is the bundles you returned in step 8, meaning in search for contacts, is it 0? If it's 0, it means you didn't find anything. If it's actually not 0, it means you found something. And I want you to create that invoice rather than create the contact a second time. The way we can actually go ahead and test this, let's actually put this particular invoice. Let's say I want to create 2 invoices straight away for the same contact. Okay. And those invoices look different. We have service number 2, service number 3. And what should happen here is it should pick both up and should work for both, but on different paths. Because when it picks this one, it's going to say, cool, I don't have— actually, let me put Upside Life 2. I don't have Ops Alive 2 in my contact database, so I'll create it. But the second time it should be like, oops, wait a second, it is there. Let's actually make sure we don't recreate it again, but we follow the other path. Let's see. That's what happened by running this workflow. Let's see what happens. So you can see the first path went through here up until in the up in the path that's here up in the first path and the other one ran through here. So if I go back to the spreadsheet, I can see that both of them were invoiced. And if I go back to the contacts, I should now also see these Opsol Live 2 version with now an invoice, with now 2 invoices, right? One that's service quantity 3. Oh, that's right. Quantity 3 and $25. That's what's $75. I was a little confused there, but that's right. That's exactly what I said. And the other invoice that has 2 of service 2 at $50. That is exactly what I shared. Now, what if I have multiple line items within the same invoice, which is often the case? And that's what I want to share with you on version 3 of this workflow, which gets a little bit more advanced, but it shows you sort of the power of some of the other built-in tools that Make has available for you. So in this example, again, I replicated version 1. You'll notice that here I'm creating the contact. Meaning I don't have that condition that we just talked about of searching the contact and creating it or not creating if it's already there. You may want to kind of expand to have both that condition from version 2 or that logic from version 2 and this from version 3. But just for demonstration purposes here, I just wanted to keep it simple and show you that these 3 steps are effectively mapping or creating an array or a bundle of items based on a comma-separated value of the columns in the spreadsheet. Let me explain what I mean. This is for splitting the descriptions by comma, the quantities, and the amounts. What that means, if I, if I say this is service, I have service as line item 1, service number 2, and service number 3 as 3 line items, and I have 1, 2, 3 of their respective quantities, and I have 100, 50, and 25. This should tell the system, hey, split this up first. So I have, you know, 3 things. Service with account 181, line item amount 100, and so on and so forth. Let's actually do this for a new contact. So live number 3, and let's put this as ready to test. It's worth noting that after I split this up, this returns me like mini, mini lists, right? Like this splits up the description so that I have now service 1, service 2, service 3. We'll see what that looks like. So this repeated module essentially is gonna make sure that I run this for as many values as I have in the spreadsheet. In this example, I have 3, right? I have service, service number 2, and service number 3. So I wanna make sure this runs 3 times. And I don't want to put a fixed value like 3 because I want to make sure I'm able to put 4 line items or 2 line items or put 10 line items or however many I want. And then we are aggregating an array that has the structure that the line items from the invoice want, and that I am mapping specifically the e value from that list, meaning This is going to run and the first time is going to create the first item with service number 1, its value, its quantity, and its amount. Then service number 2, its item and amount. And it's going to give me a bundle of line items that then I'm going to give the invoice step to have it all. This is just a quick explanation of what this does. But if I run it, we should actually see it in action and we should be able to see the logic at each of those steps. So you can see here the description. As I said, I have 3 services, 3 quantities, and 3 amounts. Here I'm running this 3 times because those have 3 values. And here I'm returning a quote unquote array that has the exact structure that the invoices want, but it's mapping. For example, the first item is the service, the second item is service 2. And this, the third item is the service 3. And now I can create that invoice. So if we go back to the spreadsheet, we should see this now as invoiced. And if I go back to contacts and I look for Observe Life 3, I should be able to open up that invoice and see those various line items mapped accordingly. As you can see here. So there you have it. That's a way in which you can very easily create invoices from zero instantly just from a spreadsheet. If you also use QuickBooks as your accounting software, I mean, you're curious to see if with a tool like Zapier, you could do something similar like this. The use case is similar, but the execution is very different. And I recorded a video in which you can learn how to do this similar use case, but with QuickBooks and Zapier, which you can watch here. So I'll see you on the next one. And until then, stay efficient. Bye.
More from Isaac

This Boring AI Automation Could Save Your Accounting Firm 40 hours (But most ignore it)

How to Build AI Systems With Claude (So Your Accounting Firm Runs Without You)









