Import Data from Salesforce to QuickBooks Online with ComponentOne Data Connectors

There are many cases where users would want to import data from Salesforce to QuickBooks Online. This blog will explore how to fetch contacts from Salesforce and import them into QuickBooks Online using ComponentOne Salesforce ADO.NET data connector and QuickBooks Online ADO.NET data connector.

To fetch contacts from Salesforce and import them to QuickBooks Online as customers, we need to consider the following steps:

  • Understanding data size and service request limits
  • Authenticate to Salesforce
  • Schema of Salesforce data
  • Fetch data from Salesforce
  • Map Salesforce data to QuickBooks Online data
  • Authenticate to QuickBooks Online
  • Insert data to QuickBooks Online

Now let’s look at each step in detail:

Data Size & Service Request Limits

Since Salesforce and QuickBooks system is available online, there are certain limits on result size and the number of calls for load balancing. This Salesforce document and QuickBooks Online document further explain the limits based on the edition and the error when the limits are exceeded.

Authenticate to Salesforce

Salesforce supports OAuth authentication for external applications that wish to connect to its REST API's. This document explains how to set up an app to enable OAuth.

The following information is required to connect to Salesforce:

  • Token endpoint
  • Client ID
  • Client secret
  • Salesforce username and password
  • Security token

Schema of Salesforce data

The schema of the entity to get data is in Salesforce here. Alternatively, you can get schema information from the connection object of ComponentOne ADO.NET data connector for Salesforce.

For the purpose of this blog, contact data is needed. The following fields are required:

  • Title
  • Salutation
  • FirstName
  • LastName
  • Id (pk to get AccountName and AccountNumber)
  • Email
  • Phone
  • MobilePhone
  • Fax
  • MailingStreet
  • MailingCity
  • MailingState
  • MailingPostalCode
  • MailingCountry
  • MailingLatitude
  • MailingLongitude

Here is the schema for the above fields as per Salesforce:

ColumnName DataType Size Nullable Creatable Updatable
AccountId System.String 18 TRUE TRUE TRUE
LastName System.String 80 FALSE TRUE TRUE
FirstName System.String 40 TRUE TRUE TRUE
Salutation System.String 40 TRUE TRUE TRUE
MailingStreet System.String 255 TRUE TRUE TRUE
MailingCity System.String 40 TRUE TRUE TRUE
MailingState System.String 80 TRUE TRUE TRUE
MailingPostalCode System.String 20 TRUE TRUE TRUE
MailingCountry System.String 80 TRUE TRUE TRUE
MailingLatitude System.String 0 TRUE TRUE TRUE
MailingLongitude System.String 0 TRUE TRUE TRUE
Phone System.String 40 TRUE TRUE TRUE
Fax System.String 40 TRUE TRUE TRUE
MobilePhone System.String 40 TRUE TRUE TRUE
Email System.String 80 TRUE TRUE TRUE
Title System.String 128 TRUE TRUE TRUE
Description System.String 32000 TRUE TRUE TRUE

Fetch Data from Salesforce

The first step towards working with the provider is to establish a connection to Salesforce. The DataConnector service library provides you with the C1SalesforceConnection class, just like the ADO.NET DbConnection class. It is used to establish a connection to the data source by creating the connection object and passing the connection string as a parameter to the class constructor. The connection string can be predefined or generated using the C1SalesforceConnectionStringBuilder class.

After initializing the connection object, we start the connection by opening it with the Open() method. Then, create a command object with the CreateCommand() method. Just like working with any DbConnection and DbCommand object, we set the SQL command using command.CommandText and command.ExecuteReader() to obtain a DataReader object to evaluate the results. In our case, we want to store results in a DataTable so DataReader is a perfect choice. The full code is as below:

        static class SalesforceSettings
            public const string OAuthTokenEndpoint = @"";
            public const string Url = @"";
            public const string ClientId = @"xxx";
            public const string ClientSecret = @"xxx";
            public const string Username = @"xxx";
            public const string Password = @"xxx";
            public const string SecurityToken = @"xxx";

        static DataTable GetContactsFromSalesforce()
            string sql = @"select c.FirstName, c.LastName, c.Salutation, c.Title, c.Email, c.Phone, c.MobilePhone, c.Fax,
                            c.MailingStreet, c.MailingCity, c.MailingState, c.MailingPostalCode, c.MailingCountry, c.MailingLatitude, c.MailingLongitude,
                            c.Description, a.Name as AccountName, a.AccountNumber From Contact c left join Account a on c.AccountId = a.Id";

            string salesforceConnection = string.Format("Username={0};Password={1};Security Token={2};OAuth Client Id={3}; OAuth Client Secret={4}; OAuth Token Endpoint={5}; Url={6}",
                SalesforceSettings.Username, SalesforceSettings.Password, SalesforceSettings.SecurityToken, SalesforceSettings.ClientId, SalesforceSettings.ClientSecret,
                SalesforceSettings.OAuthTokenEndpoint, SalesforceSettings.Url);

            using (var con = new C1SalesforceConnection(salesforceConnection))
                var command = con.CreateCommand();
                command.CommandText = sql;

                var contactsReader = command.ExecuteReader();
                var dataTable = new DataTable();
                return dataTable;

Map Salesforce Data to QuickBooks Online Data

Use the following table to map fields between QuickBooks Online Customer with Salesforce Contact

QBO Customers Salesforce Contacts
Title Title
Suffix Salutation
GivenName FirstName
FamilyName LastName
CompanyName Account.Id (link to AccountName)
PrimaryEmailAddr_Address Email
PrimaryPhone_FreeFormNumber Phone
Mobile_FreeFormNumber MobilePhone
Fax_FreeFormNumber Fax
BillAddr_City MailingCity
BillAddr_CountrySubDivisionCode MailingState
BillAddr_PostalCode MailingPostalCode
BillAddr_Country MailingCountry
BillAddr_Lat MailingLatitude
BillAddr_Long MailingLongitude
Notes Description

Authenticate to QuickBooks Online

The first step towards working with the provider is to establish a connection to the QuickBooks Online data. The DataConnector service library provides you with the C1QuickBooksOnlineConnection class, just like the ADO.NET DbConnection class. It is used to establish a connection to the data source by creating the connection object and passing the connection string as a parameter to the class constructor. The connection string can be predefined or generated using the C1QuickBooksOnlineConnectionStringBuilder class.

The values for OAuthAccessToken, OAuthRefreshToken must be generated using the browser and following these steps.

Here is a sample code snippet depicting how to generate a connection string and create a connection object:

        static class QBOSettings
            public static string OAuthAccessToken = @"xxx";
            public static string OAuthRefreshToken = @"xxx";
            public const string OAuthClientId = @"xxx";
            public const string OAuthClientSecret = @"xxx";
            public static string CompanyId = "xxx";
            public const string MinorVersion = "xxx";

            public static string ConnectionString => $"Company Id={CompanyId};Use SandBox=true;OAuth Client Secret={OAuthClientSecret};OAuth Client Id={OAuthClientId};" +
                            $"OAuth Access Token={OAuthAccessToken};OAuth Refresh Token={OAuthRefreshToken}; OAuth Token Endpoint=;Minor Version={MinorVersion}";

            using (var conn = new C1QuickBooksOnlineConnection(QBOSettings.ConnectionString))
                conn.OAuthTokenRefreshed += OnOAuthTokenRefreshed;

Insert Data into QuickBooks Online

Using the DataTable returned from the GetContactsFromSalesforce method, we will use C1QuickBooksOnlineDataAdapter to bulk insert data to QuickBooks Online.

C1QuickBooksOnlineDataAdapter inherits DbDataAdapter so it provides all the usual functionalities of a DbDataAdapter.

                C1QuickBooksOnlineDataAdapter dataAdapter = new C1QuickBooksOnlineDataAdapter();
                var insertCmd = "Insert Into Customers(Title, GivenName, FamilyName, CompanyName, PrimaryPhone_FreeFormNumber," +
                    "Mobile_FreeFormNumber, Fax_FreeFormNumber, BillAddr_City, BillAddr_CountrySubDivisionCode, BillAddr_PostalCode, BillAddr_Country, BillAddr_Lat," +
                    "BillAddr_Long, Notes) VALUES (@p1, @p2, @p3, @p4, @p6, @p7, @p8, @p9, @p10, @p11, @p12, @p13, @p14, @p15)";

                dataAdapter.InsertCommand = new C1QuickBooksOnlineCommand(conn, insertCmd);
                dataAdapter.InsertCommand.Parameters.Add("@p1", DbType.String, "Salutation");
                dataAdapter.InsertCommand.Parameters.Add("@p2", DbType.String, "FirstName");
                dataAdapter.InsertCommand.Parameters.Add("@p3", DbType.String, "LastName");
                dataAdapter.InsertCommand.Parameters.Add("@p4", DbType.String, "AccountName");
                dataAdapter.InsertCommand.Parameters.Add("@p6", DbType.String, "Phone");
                dataAdapter.InsertCommand.Parameters.Add("@p7", DbType.String, "MobilePhone");
                dataAdapter.InsertCommand.Parameters.Add("@p8", DbType.String, "Fax");
                dataAdapter.InsertCommand.Parameters.Add("@p9", DbType.String, "MailingCity");
                dataAdapter.InsertCommand.Parameters.Add("@p10", DbType.String, "MailingState");
                dataAdapter.InsertCommand.Parameters.Add("@p11", DbType.String, "MailingPostalCode");
                dataAdapter.InsertCommand.Parameters.Add("@p12", DbType.String, "MailingCountry");
                dataAdapter.InsertCommand.Parameters.Add("@p13", DbType.String, "MailingLatitude");
                dataAdapter.InsertCommand.Parameters.Add("@p14", DbType.String, "MailingLongitude");
                dataAdapter.InsertCommand.Parameters.Add("@p15", DbType.String, "Description");
                dataAdapter.InsertCommand.UpdatedRowSource = UpdateRowSource.None;

                //Need to change row state to added for bulk insert to work
                dataTable.TableName = "Customers";
                foreach (DataRow curRow in dataTable.Rows)

                dataAdapter.UpdateBatchSize = 100;
                int rowAffected = dataAdapter.Update(dataTable);

That’s it! With ComponentOne Salesforce and QuickBooks Online ADO.NET data connectors, we can manipulate data easily between these common data platforms. See our Desktop DataConnectors Explorer or Web DataConnectors Explorer for more data connector demos.

Hans Nguyen

Software Engineer
comments powered by Disqus