Introduction
QuickBooks is a small-business accounting software made by Intuit. It has online
and desktop editions (Pro, Premier, etc.). It is widely used and Intuit provided
an SDK so that third-party applications can access or write QuickBooks data.
Applications communicate with QuickBooks using XML for requests and responses.
Fortunately for us .NET developers, Intuit also provided the QBFC Library so
we can use C# or VB to build requests or accept responses, although XML (or qbXML
as Intuit calls it) is still used internally. I find very few articles regarding
the integration of a .NET application with QuickBooks for desktop, which makes
it hard for developers just beginning programming with QuickBooks.
Getting Started
In this article, I’ll be creating a WPF application that can add, update, and get
some data to and from the QuickBooks company file. For this, we need to have
QuickBooks and the QuickBooks SDK installed in our development machine. You can
get these from Intuit’s website. The following figure shows the demo application.

Figure 1. Example WPF Application
This application allows the user to add, update, delete and view customers, invoices
and items. The right panel content changes according to what Button the user
clicked on the left panel. In the figure above, the right panel shows the form
for adding, updating or deleting a customer. This form contains a Name and a
QuickBooks ID field. The QuickBooks ID field is not editable and will have a
value after saving the new customer. Let us implement adding of a customer. In
the Save Button’s Click event handler, we will connect to QuickBooks and send
a request for adding a customer. To use QBFC in our .NET application, we have
to add a reference to the QBFC library. This is found under the COM Tab in the
Add Reference dialog. In the example, we’ll be adding qbFC10 1.0 Type Library.

Figure 2. Add Reference to QBFC Library
In writing code for making requests to QuickBooks, the best reference material to
check is the Unified Onscreen Reference (OSR). It is installed along with the
QuickBooks SDK or can be accessed online at http://developer.intuit.com/qbSDK-Current/Common/newOSR/index.html.
This is useful when checking what fields are required when making requests. There
are also examples on how to create requests using C# and VB .NET. Since we are
interested in adding a customer in QuickBooks, we will select the CustomerAdd
message as shown in the figure below. In the Request tab, you can see that the
only required field is the Name field.

Figure 3. CustomerAdd Message in Unified Onscreen Reference
Aside from checking what the required fields are, there are also other things we
can see in the OSR worth noting like the maximum number (Desktop or Online Edition
may differ) of characters for a string-type field or what version of QuickBooks
is a field supported. Under the C# tab, there is an example code that we can
copy and modify. The example code sets all fields of the request and is more
of a guide due to a lot of comments rather than a working example. It might not
compile because strings are used in some fields instead of values of the correct
types. Going back to our example, we just need to set the required fields. The
following code listing shows how to create a customer in QuickBooks via QBFC.
I copied the code from the OSR and modified it a bit.
private void SaveBtn_Click(object sender, RoutedEventArgs e)
{
bool sessionBegun = false;
bool connectionOpen = false;
QBSessionManager sessionManager = null;
try
{
//Create the session Manager object
sessionManager = new QBSessionManager();
//Create the message set request object to hold our request
IMsgSetRequest requestMsgSet = sessionManager.CreateMsgSetRequest("US", 8, 0);
requestMsgSet.Attributes.OnError = ENRqOnError.roeContinue;
//Connect to QuickBooks and begin a session
sessionManager.OpenConnection(@"C:\Users\Public\Documents\Intuit\QuickBooks\Company Files\My Company.QBW", "QuickBooks Integration Demo");
connectionOpen = true;
sessionManager.BeginSession("", ENOpenMode.omDontCare);
sessionBegun = true;
ICustomerAdd customerAddRq = requestMsgSet.AppendCustomerAddRq();
customerAddRq.Name.SetValue(Customer.Name);
//Send the request and get the response from QuickBooks
IMsgSetResponse responseMsgSet = sessionManager.DoRequests(requestMsgSet);
IResponse response = responseMsgSet.ResponseList.GetAt(0);
ICustomerRet customerRet = (ICustomerRet)response.Detail;
Customer.QuickBooksID = customerRet.ListID.GetValue();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error");
}
finally
{
//End the session and close the connection to QuickBooks
if (sessionBegun)
{
sessionManager.EndSession();
}
if (connectionOpen)
{
sessionManager.CloseConnection();
}
}
}
Listing 1. Creating a Customer
The following are the usual steps in making requests to QuickBooks.
1. Create a session manager
2. Open a connection
3. Create a session
4. Create a set of requests
5. Add requests to the set
6. Perform the requests
7. Process the response
8. End the session
9. Close the connection
In the OpenConnection method, we have to specify the path of the company file to
be accessed, and the name of the application that will access the company file.
If we specify an empty string for the company file path, the current company
file that is opened in QuickBooks will be used. In the CreateMsgSetRequest method,
you can see that we passed some parameters. These parameters indicate what versions
of QuickBooks and qbXML/QBFC the request is targeted at. To check what qbXML
specification version is supported by your QuickBooks software, you can check
the release notes under the Intuit SDKs folder on the Start menu. After getting
an IMsgSetRequest object, we can append requests to it, as shown in the above
code when we called the AppendCustomerAddRq method. We then called the DoRequests
method to process the requests. This method returns an IMsgSetResponse object,
which contains a list of responses, in the form of IResponse objects. Each response
corresponds to a request. To get a specific response, we have to use the GetAt
method and pass the index of the response. An IResponse object has a Detail property
which we can then cast to the appropriate object, ICustomerRet in the above example.
Assuming that we haven’t opened QuickBooks yet and we try to save a new customer
using the demo application, we will get the following exception message: Could
not start QuickBooks. The reason is that the application is not yet authorized
to access the QuickBooks company file.
Authorizing the Application
On the first time that an application connects to a QuickBooks company file, QuickBooks
should be opened and a user is there to authorize the access. When we try to
save a customer again and QuickBooks is running this time, a dialog will appear
in QuickBooks, as shown in the figure below. We should take note that this will
block the current thread so if we used the UI thread, then the UI will become
unresponsive.

Figure 4. Authorize Application Access in QuickBooks
In the figure above, you can see that the currently opened file is called My Company.
Here, we may or may not allow the application have access to the company file.
We can also specify whether to prompt us every time the application tries to
access the company file or always allow the application to access the company
file whether QuickBooks is running or not. In our example, let us allow the application
to access the company file even if QuickBooks is not running. After clicking
on the Continue… Button, we will see that the customer is added to QuickBooks.

Figure 5. Added Customer in QuickBooks
After the customer is added to the company file, it is given a unique ID within the
list of customers, which is called ListID in QuickBooks. In the demo application,
the ListID is shown in the QuickBooks ID TextBox.

Figure 6. Customer ListID
Other objects like inventory items and vendors also have ListIDs. The IDs of transactions,
like invoices and purchase orders, are called TxnIDs. The ListID is like an auto-increment
primary key in SQL Server. Using the ListID, we can get a list object like a
customer and update the customer information. Aside from the ListID, the FullName
field is also used to uniquely identify a list object in QuickBooks. A FullName
is the Name of the list object prefixed with its ancestors’ names. You can think
of an ancestor as a category of a list object. To assign a parent to a list object,
we have to specify a value in the ParentRef field. In our example, we did not
specify a value for this field. Adding a customer of the same name without a
different parent will give us an error.
Getting Customers
To get a specific customer, we can use the CustomerQuery method and specify either
a ListID or FullName. If both ListID and FullName are specified, the FullName
will be ignored. In the demo application however, we will be getting all customers
so we won’t be setting the ListID or FullName in the query. When the View All
Customers Button is clicked, the right panel will show a DataGrid of customers.
The DataGrid is filled with customer details when it is loaded. The following
code snippet shows a part of the DataGrid’s Loaded event handler. For brevity,
I did not include some parts like creating the session manager and disposing
of it.
ICustomerQuery customerQueryRq = requestMsgSet.AppendCustomerQueryRq();
//Send the request and get the response from QuickBooks
IMsgSetResponse responseMsgSet = sessionManager.DoRequests(requestMsgSet);
IResponse response = responseMsgSet.ResponseList.GetAt(0);
ICustomerRetList customerRetList = (ICustomerRetList)response.Detail;
var customers = new List<Customer>();
if (customerRetList != null)
{
for (int i = 0; i < customerRetList.Count; i++)
{
ICustomerRet customerRet = customerRetList.GetAt(i);
var customer = new Customer
{
Name = customerRet.Name.GetValue(),
QuickBooksID = customerRet.ListID.GetValue(),
EditSequence = customerRet.EditSequence.GetValue()
};
customers.Add(customer);
}
}
customersDataGrid.ItemsSource = customers;
Listing 2. Getting the List of Customers
You can notice the differences between getting customers and adding a customer. Here
we used the AppendCustomerQueryRq method. Also, the Detail property of the IResponse
object is an ICustomerRetList object. We can get individual ICustomerRet objects
by using the GetAt method. To get the information we need like Name and ListID,
remember to use the GetValue method. If we looked at the CustomerQuery message
in the Onscreen Reference, we will see fields that we can set to filter the results
of the query. For example, we can set the ListIDList so that the query will only
return customers that have a matching ListID in the ListIDList. There is also
a NameFilter field where we can match a customer using a name. We can also specify
whether the query returns the count only, data only, or both using the metaData
field. The metaData field is useful when we only want to know the number of results
and do not want to load all of the query results into memory since we might be
working on thousands of records. Another interesting field is the IncludeRetElementList.
Using this, we can specify what fields of the results will have values to limit
the data returned by QuickBooks. In our example above, we can add the Name, ListID,
and EditSequence fields to the IncludeRetElementList since these are the only
fields we are currently interested in. Check out the Onscreen Reference for other
fields that you can set. The following figure shows the DataGrid containing the
new customer.

Figure 7. List of Customers
In the DataGrid, I have added a Modify Button so that we can edit the customer name
(since that is the only field that we can edit in the application). Clicking
on the Modify Button will show the customer details on the same form used for
adding a customer.
Modifying a Customer
Since adding and modifying a customer is almost the same, I just used the same form
although I modified the Save Button’s event handler. The application will determine
whether to add or modify a customer object by checking if the QuickBooksID property
has a value. Here is the updated code.
if (Customer.QuickBooksID == null)
{
ICustomerAdd customerAddRq = requestMsgSet.AppendCustomerAddRq();
customerAddRq.Name.SetValue(Customer.Name);
//Send the request and get the response from QuickBooks
IMsgSetResponse responseMsgSet = sessionManager.DoRequests(requestMsgSet);
IResponse response = responseMsgSet.ResponseList.GetAt(0);
ICustomerRet customerRet = (ICustomerRet)response.Detail;
Customer.QuickBooksID = customerRet.ListID.GetValue();
}
else
{
ICustomerMod customerModRq = requestMsgSet.AppendCustomerModRq();
customerModRq.Name.SetValue(Customer.Name);
customerModRq.ListID.SetValue(Customer.QuickBooksID);
customerModRq.EditSequence.SetValue(Customer.EditSequence);
//Send the request to QuickBooks
sessionManager.DoRequests(requestMsgSet);
}
Listing 3. Adding or Modifying a Customer
In the preceding code, we used the Customer’s QuickBooksID property to determine
whether to add or modify a customer. The Customer object is set in the constructor.
To modify a customer, we have to use the AppendCustomerModRq method. Aside from
setting the Name and ListID fields, we also need to set the required EditSequence
field.
The EditSequence field value is generated by QuickBooks for an object and ensures
that we won’t be able to modify the object if we are not working on the latest
copy. This is useful when there are other people modifying data in QuickBooks.
This prevents us from overwriting other people’s modifications. For example,
we queried an object from QuickBooks and we are given an EditSequence value.
We then passed this EditSequence value along with the request to modify the object.
QuickBooks will then compare the EditSequence we passed and the latest EditSequence.
If they are the same, the request succeeds. However, if someone modified the
object before we can submit our request, then the latest EditSequence will be
different and our request will fail. In the demo application, clicking on the
Save Button twice (without refreshing the list of customers) would give us an
error like the following "The provided edit sequence "1291625289"
is out-of-date."
Deleting a List Object
Deleting a list object is a bit different from creating or modifying it. For a customer
list object, we have requests like ICustomerAdd, ICustomerMod and ICustomerQuery.
However, the QuickBooks SDK does not have an ICustomerDel. Instead, there is
an IListDel request, which is the request used for deleting list objects. You
can specify what type of list object to delete using the ListDelType field, as
shown in the following code snippet.
IListDel listDelRq = requestMsgSet.AppendListDelRq();
listDelRq.ListDelType.SetValue(ENListDelType.ldtCustomer);
listDelRq.ListID.SetValue(qbIdTbx.Text);
//Send the request to QuickBooks
sessionManager.DoRequests(requestMsgSet);
Listing 4. Deleting a Customer
Clicking on the Delete Button will delete the customer from QuickBooks. However,
if the customer had been referenced by a transaction, say an invoice, the customer
can’t be deleted. You can either make the customer inactive or delete first all
the transactions that reference the customer.
Differences between Customer and Item
Before we can make a sales invoice, we should have a customer and the items the customer
bought. We already have the code for adding customers in our application, leaving
us with the code for creating items. Although customer and item types are both
list objects in QuickBooks, there are some differences we need to know of. Here’s
the code for adding or modifying an item in the demo application.
if (Item.QuickBooksID == null)
{
if (Item.ItemType == ItemType.Inventory)
{
IItemInventoryAdd itemInventoryAddRq = requestMsgSet.AppendItemInventoryAddRq();
itemInventoryAddRq.Name.SetValue(Item.Name);
itemInventoryAddRq.SalesDesc.SetValue(Item.Description);
itemInventoryAddRq.SalesPrice.SetValue(Item.Rate);
itemInventoryAddRq.IncomeAccountRef.FullName.SetValue("Sales - Hardware");
itemInventoryAddRq.AssetAccountRef.FullName.SetValue("Inventory");
itemInventoryAddRq.COGSAccountRef.FullName.SetValue("Purchases - Hardware for Resale");
//Send the request and get the response from QuickBooks
IMsgSetResponse responseMsgSet = sessionManager.DoRequests(requestMsgSet);
IResponse response = responseMsgSet.ResponseList.GetAt(0);
IItemInventoryRet itemInventoryRet = (IItemInventoryRet)response.Detail;
Item.QuickBooksID = itemInventoryRet.ListID.GetValue();
}
else // ItemType.Service
{
IItemServiceAdd itemServiceAddRq = requestMsgSet.AppendItemServiceAddRq();
itemServiceAddRq.Name.SetValue(Item.Name);
itemServiceAddRq.ORSalesPurchase.SalesOrPurchase.Desc.SetValue(Item.Description);
itemServiceAddRq.ORSalesPurchase.SalesOrPurchase.ORPrice.Price.SetValue(Item.Rate);
itemServiceAddRq.ORSalesPurchase.SalesOrPurchase.AccountRef.FullName.SetValue("Sales - Support and Maintenance");
//Send the request and get the response from QuickBooks
IMsgSetResponse responseMsgSet = sessionManager.DoRequests(requestMsgSet);
IResponse response = responseMsgSet.ResponseList.GetAt(0);
IItemServiceRet itemServiceRet = (IItemServiceRet)response.Detail;
Item.QuickBooksID = itemServiceRet.ListID.GetValue();
}
}
else
{
if (Item.ItemType == ItemType.Inventory)
{
IItemInventoryMod itemInventoryModRq = requestMsgSet.AppendItemInventoryModRq();
itemInventoryModRq.Name.SetValue(Item.Name);
itemInventoryModRq.SalesDesc.SetValue(Item.Description);
itemInventoryModRq.SalesPrice.SetValue(Item.Rate);
itemInventoryModRq.ListID.SetValue(Item.QuickBooksID);
itemInventoryModRq.EditSequence.SetValue(Item.EditSequence);
//Send the request to QuickBooks
sessionManager.DoRequests(requestMsgSet);
}
else // ItemType.Service
{
IItemServiceMod itemServiceModRq = requestMsgSet.AppendItemServiceModRq();
itemServiceModRq.Name.SetValue(Item.Name);
itemServiceModRq.ORSalesPurchaseMod.SalesOrPurchaseMod.Desc.SetValue(Item.Description);
itemServiceModRq.ORSalesPurchaseMod.SalesOrPurchaseMod.ORPrice.Price.SetValue(Item.Rate);
itemServiceModRq.ListID.SetValue(Item.QuickBooksID);
itemServiceModRq.EditSequence.SetValue(Item.EditSequence);
//Send the request to QuickBooks
sessionManager.DoRequests(requestMsgSet);
}
}
Listing 5. Adding or Modifying an Item
There are several types of items in QuickBooks. There are inventory, non-inventory,
and service items, among others. I only used inventory and service items in the
demo application. In the preceding code, you can see that there are different
requests for the different types of items. That is because different types of
items will have different fields. An inventory item has a QuantityOnHand field
while a service item doesn’t. Some requests also require that you reference income
accounts, asset accounts, etc. On the other hand, deleting an item doesn’t differ
much from deleting a customer. We just need to use an if-else construct again
to determine whether to delete an inventory or service item.
IListDel listDelRq = requestMsgSet.AppendListDelRq();
listDelRq.ListID.SetValue(Item.QuickBooksID);
if (Item.ItemType == ItemType.Inventory)
{
listDelRq.ListDelType.SetValue(ENListDelType.ldtItemInventory);
}
else // ItemType.Service
{
listDelRq.ListDelType.SetValue(ENListDelType.ldtItemService);
}
//Send the request to QuickBooks
sessionManager.DoRequests(requestMsgSet);
Listing 6. Deleting an Item
When querying items from QuickBooks, we have an option to use the different requests
for the different types of items. Some requests are IItemInventoryQuery and IItemServiceQuery.
We can also get all the items, regardless of type, by using the IItemQuery request.
This is what we used in viewing all the items in the demo application.
IItemQuery itemQueryRq = requestMsgSet.AppendItemQueryRq();
//Send the request and get the response from QuickBooks
IMsgSetResponse responseMsgSet = sessionManager.DoRequests(requestMsgSet);
IResponse response = responseMsgSet.ResponseList.GetAt(0);
IORItemRetList itemRetList = (IORItemRetList)response.Detail;
var items = new List<Item>();
if (itemRetList != null)
{
for (int i = 0; i < itemRetList.Count; i++)
{
IORItemRet itemRet = itemRetList.GetAt(i);
if (itemRet.ItemInventoryRet != null)
{
IItemInventoryRet itemInventoryRet = itemRet.ItemInventoryRet;
var item = new Item
{
Name = itemInventoryRet.Name.GetValue(),
Description = itemInventoryRet.SalesDesc.GetValue(),
Rate = itemInventoryRet.SalesPrice.GetValue(),
ItemType = ItemType.Inventory,
QuickBooksID = itemInventoryRet.ListID.GetValue(),
EditSequence = itemInventoryRet.EditSequence.GetValue()
};
items.Add(item);
}
else if (itemRet.ItemServiceRet != null)
{
IItemServiceRet itemServiceRet = itemRet.ItemServiceRet;
var item = new Item
{
Name = itemServiceRet.Name.GetValue(),
Description = itemServiceRet.ORSalesPurchase.SalesOrPurchase.Desc.GetValue(),
Rate = itemServiceRet.ORSalesPurchase.SalesOrPurchase.ORPrice.Price.GetValue(),
ItemType = ItemType.Service,
QuickBooksID = itemServiceRet.ListID.GetValue(),
EditSequence = itemServiceRet.EditSequence.GetValue()
};
items.Add(item);
}
}
}
itemsDataGrid.ItemsSource = items;
Listing 7. Getting All Items
In the preceding code, the Detail property of the IResponse object is of type IORItemRetList.
It is the list of the items we queried and we can get individual IORItemRet objects
by using the GetAt method. The actual item object is stored in one of the IORItemRet
properties. If the item is of type IItemServiceRet, then it is stored in the
IORItemRet’s ItemServiceRet property. By checking if a property is not null,
we can determine the type of the item.
Creating an Invoice
To create an invoice, we are required to pass a reference to the customer and the
items he purchased. That is why I showed how to create customers and items first.
In the demo application, we have the following form used for creating or modifying
an invoice.

Figure 8. Invoice Form
In the example above, we have an existing customer named test and an item called
part 1. After the invoice has been saved, the invoice will have an assigned transaction
ID. This will be shown in the QuickBooks ID TextBox. An invoice can contain the
items purchased by the customer and each row in the DataGrid corresponds to an
invoice line in QuickBooks. An invoice line is also assigned a unique ID, which
we can refer to as transaction line ID. Here is a screenshot of the application
after saving the sample invoice.

Figure 9. Saved Invoice
The code for adding an invoice is not much different from creating a customer. We
just have to specify the invoice lines. To add an invoice line, we can append
an IORInvoiceLineAdd request to the ORInvoiceLineAddList property of the IInvoiceAdd
request. We don’t directly append it to the IMsgSetRequest object.
IInvoiceAdd invoiceAddRq = requestMsgSet.AppendInvoiceAddRq();
invoiceAddRq.CustomerRef.ListID.SetValue(Invoice.Customer.QuickBooksID);
foreach (InvoiceItem invoiceItem in Invoice.InvoiceItems)
{
IORInvoiceLineAdd orInvoiceLineAdd = invoiceAddRq.ORInvoiceLineAddList.Append();
orInvoiceLineAdd.InvoiceLineAdd.ItemRef.ListID.SetValue(invoiceItem.Item.QuickBooksID);
orInvoiceLineAdd.InvoiceLineAdd.Amount.SetValue(invoiceItem.Amount);
}
//Send the request and get the response from QuickBooks
IMsgSetResponse responseMsgSet = sessionManager.DoRequests(requestMsgSet);
IResponse response = responseMsgSet.ResponseList.GetAt(0);
IInvoiceRet invoiceRet = (IInvoiceRet)response.Detail;
Invoice.QuickBooksID = invoiceRet.TxnID.GetValue();
for (int i = 0; i < invoiceRet.ORInvoiceLineRetList.Count; i++)
{
Invoice.InvoiceItems[i].QuickBooksID = invoiceRet.ORInvoiceLineRetList.GetAt(i).InvoiceLineRet.TxnLineID.GetValue();
}
Listing 8. Adding an Invoice
Meanwhile, modifying an invoice deserves a little more explanation.
Modifying an Invoice
To modify an invoice, we need to use the IInvoiceMod request. However, it is not
as straightforward as editing a customer since an invoice has invoice lines.
We can delete an invoice line from an invoice, modify an invoice line, or add
a new one. Strictly speaking, we cannot actually delete an invoice line. However,
we can replace the existing invoice lines with a new set of invoice lines. To
make it look like we deleted an invoice line, we can pass the same set of invoice
lines minus the invoice line we want to delete. Since we are replacing invoice
lines to mimic a deletion, we cannot delete an invoice line if it is the only
invoice line in the invoice. Here is the code for modifying an invoice.
IInvoiceMod invoiceModRq = requestMsgSet.AppendInvoiceModRq();
invoiceModRq.CustomerRef.ListID.SetValue(Invoice.Customer.QuickBooksID);
invoiceModRq.TxnID.SetValue(Invoice.QuickBooksID);
invoiceModRq.EditSequence.SetValue(Invoice.EditSequence);
foreach (InvoiceItem invoiceItem in Invoice.InvoiceItems)
{
IORInvoiceLineMod orInvoiceLineMod = invoiceModRq.ORInvoiceLineModList.Append();
if (invoiceItem.QuickBooksID == null)
orInvoiceLineMod.InvoiceLineMod.TxnLineID.SetValue("-1");
else
orInvoiceLineMod.InvoiceLineMod.TxnLineID.SetValue(invoiceItem.QuickBooksID);
orInvoiceLineMod.InvoiceLineMod.ItemRef.ListID.SetValue(invoiceItem.Item.QuickBooksID);
orInvoiceLineMod.InvoiceLineMod.Amount.SetValue(invoiceItem.Amount);
}
//Send the request to QuickBooks
IMsgSetResponse responseMsgSet = sessionManager.DoRequests(requestMsgSet);
IResponse response = responseMsgSet.ResponseList.GetAt(0);
IInvoiceRet invoiceRet = (IInvoiceRet)response.Detail;
for (int i = 0; i < invoiceRet.ORInvoiceLineRetList.Count; i++)
{
if (Invoice.InvoiceItems[i].QuickBooksID == null)
Invoice.InvoiceItems[i].QuickBooksID =
invoiceRet.ORInvoiceLineRetList.GetAt(i).InvoiceLineRet.TxnLineID.GetValue();
}
Listing 9. Modifying an Invoice
To modify an existing invoice line, we need to append an IORInvoiceLineMod request
and set its InvoiceLineMod.TxnLineID property to the transaction line ID of the
invoice line. If we want to add a new invoice line, we have to set the TxnLineID
to “-1” as you can see in the preceding code listing.
Getting Invoices
The code for getting invoices is a bit longer because we also need to get the details
of the customer and the items referenced by the invoice. By default, invoice
lines are not included in the query results so we have to set the IncludeLineItems
property to true.
IInvoiceQuery invoiceQueryRq = requestMsgSet.AppendInvoiceQueryRq();
invoiceQueryRq.IncludeLineItems.SetValue(true);
//Send the request and get the response from QuickBooks
IMsgSetResponse responseMsgSet = sessionManager.DoRequests(requestMsgSet);
IResponse response = responseMsgSet.ResponseList.GetAt(0);
IInvoiceRetList invoiceRetList = (IInvoiceRetList)response.Detail;
var invoices = new List<Invoice>();
if (invoiceRetList != null)
{
for (int i = 0; i < invoiceRetList.Count; i++)
{
IInvoiceRet invoiceRet = invoiceRetList.GetAt(i);
var invoice = new Invoice
{
QuickBooksID = invoiceRet.TxnID.GetValue(),
EditSequence = invoiceRet.EditSequence.GetValue()
};
requestMsgSet.ClearRequests();
ICustomerQuery customerQueryRq = requestMsgSet.AppendCustomerQueryRq();
customerQueryRq.ORCustomerListQuery.ListIDList.Add(invoiceRet.CustomerRef.ListID.GetValue());
//Send the request and get the response from QuickBooks
responseMsgSet = sessionManager.DoRequests(requestMsgSet);
response = responseMsgSet.ResponseList.GetAt(0);
ICustomerRetList customerRetList = (ICustomerRetList)response.Detail;
ICustomerRet customerRet = customerRetList.GetAt(0);
invoice.Customer = new Customer
{
Name = customerRet.Name.GetValue(),
QuickBooksID = customerRet.ListID.GetValue(),
EditSequence = customerRet.EditSequence.GetValue()
};
if (invoiceRet.ORInvoiceLineRetList != null)
{
for (int j = 0; j < invoiceRet.ORInvoiceLineRetList.Count; j++)
{
IORInvoiceLineRet ORInvoiceLineRet = invoiceRet.ORInvoiceLineRetList.GetAt(j);
var invoiceItem = new InvoiceItem
{
Amount = ORInvoiceLineRet.InvoiceLineRet.Amount.GetValue(),
QuickBooksID = ORInvoiceLineRet.InvoiceLineRet.TxnLineID.GetValue()
};
requestMsgSet.ClearRequests();
IItemQuery itemQueryRq = requestMsgSet.AppendItemQueryRq();
itemQueryRq.ORListQuery.ListIDList.Add(ORInvoiceLineRet.InvoiceLineRet.ItemRef.ListID.GetValue());
//Send the request and get the response from QuickBooks
responseMsgSet = sessionManager.DoRequests(requestMsgSet);
response = responseMsgSet.ResponseList.GetAt(0);
IORItemRetList itemRetList = (IORItemRetList)response.Detail;
IORItemRet itemRet = itemRetList.GetAt(0);
if (itemRet.ItemInventoryRet != null)
{
IItemInventoryRet itemInventoryRet = itemRet.ItemInventoryRet;
var item = new Item
{
Name = itemInventoryRet.Name.GetValue(),
Description = itemInventoryRet.SalesDesc.GetValue(),
Rate = itemInventoryRet.SalesPrice.GetValue(),
ItemType = ItemType.Inventory,
QuickBooksID = itemInventoryRet.ListID.GetValue(),
EditSequence = itemInventoryRet.EditSequence.GetValue()
};
invoiceItem.Item = item;
}
else if (itemRet.ItemServiceRet != null)
{
IItemServiceRet itemServiceRet = itemRet.ItemServiceRet;
var item = new Item
{
Name = itemServiceRet.Name.GetValue(),
Description = itemServiceRet.ORSalesPurchase.SalesOrPurchase.Desc.GetValue(),
Rate = itemServiceRet.ORSalesPurchase.SalesOrPurchase.ORPrice.Price.GetValue(),
ItemType = ItemType.Service,
QuickBooksID = itemServiceRet.ListID.GetValue(),
EditSequence = itemServiceRet.EditSequence.GetValue()
};
invoiceItem.Item = item;
}
invoice.InvoiceItems.Add(invoiceItem);
}
}
invoices.Add(invoice);
}
}
invoicesDataGrid.ItemsSource = invoices;
Listing 10. Getting Invoices
In the above code, we have several requests: get an invoice, get the referenced customer,
and get the referenced items. The same IMsgSetRequest object is used for these
requests and the ClearRequests method is used to remove existing requests in
the set so they are not processed more than once.
Deleting a Transaction
Deleting a transaction is similar to deleting a list object. We have to specify the
type of transaction to delete and the ID of the transaction. The difference is
that we will use an ITxnDel request instead of IListDel.
ITxnDel txnDelRq = requestMsgSet.AppendTxnDelRq();
txnDelRq.TxnDelType.SetValue(ENTxnDelType.tdtInvoice);
txnDelRq.TxnID.SetValue(Invoice.QuickBooksID);
//Send the request to QuickBooks
sessionManager.DoRequests(requestMsgSet);
Listing 11. Delete a Transaction
I hope I covered at least the basics of programming with .NET and QuickBooks using
the QBFC Library. The Visual Studio 2010 solution of the demo application can
be downloaded here.