Requests that use the unit of measure feature

The unit of measure (UOM) feature allows you to define the unit that can be used to express an item’s quantity, prices, rates, and costs. For example, if you enter a quantity of 25 on an invoice for a ball point pen item, the unit of measure used shows whether that quantity means 25 individual pens, 25 boxes of 12, or 25 cases containing 120 pens each. The unit of measure feature must be activated through the QuickBooks UI, at the level of a company file. A QuickBooks company file can be set to use the feature in either of two ways:

SDK support of the UOM feature began with qbXML spec 7.0 and QB 2008. The intention of the Desktop SDK’s implementation is to allow applications to use UOM in a manner similar to the way an the interactive user uses it in the QuickBooks UI.

This page introduces the UOM feature and explains how to use it with the SDK.

UOM workflow in the QuickBooks UI

This section introduces the UOM feature by looking at the UOM workflow in the QuickBooks UI. Note that the feature must be activated in the company file before this workflow can begin.

  1. Create a UOM set with a base unit and, if the company is configured for multiple units of measure, define any related units, which will be multiples of the base unit. For example, for a company that is configured for multiple units of measure, a UOM set named “By the crate” could establish the following units:

    ../../../../_images/Image_454.jpg
  2. Assign the UOM set to the item. This can be done either when creating or modifying an item, . Once a set is assigned to an item, any of the units in the set can be used for the item. For example, after the UOM set “by the crate” has been assigned to eggs, eggs can be listed by the crate, by the half-crate, or by the carton.

    ../../../../_images/Image_455.jpg

    The next figure shows how a defined UOM set is available for selection in the QuickBooks UI:

    ../../../../_images/Image_456.jpg
  3. Transactions that include the item can be quantified with any of the units of measure in the UOM set. Continuing with the egg example, an invoice line for eggs gets units from the UOM set assigned to ItemRef:

    ../../../../_images/Image_457.jpg

    The next figure shows how, in the QuickBooks UI, the defined UOM units are available for a particular transaction line:

    ../../../../_images/Image_458.jpg

    Again the above figure holds true only in multiple UOM mode. In single UOM per item, there is no dropdown list and the U/M is listed but greyed out, disinviting any user selection, because only the base unit is allowed. Even in the SDK, if the company file is set to single UOM per item, you can only specify the base unit. Specifying some other unit will result in an error status code of 3210.

Unfortunately there is currently no way to determine whether the company file is in single UOM or multiple UOM mode, other than perhaps checking for error 3210 when assigning a non-base unit to a transaction line.

Creating a UOM set in the QuickBooks UI

In the QuickBooks UI, if the company is enabled for multiple UOMs per item, a UOM can be created either from the UOM set list (Lists->U/M Set List->U/M Set->New) as shown below, or from the New or Edit Item forms by clicking Add New within the U/M Set dropdown listbox:

../../../../_images/Image_460.jpg

If the company file is enabled for single UOM per item, then you simply create a new UOM in the U/M dropdown list by clicking <Add New>. QuickBooks will then create a default UOM set for that new UOM, and assign that unit as the base unit and name the UOM set “By the unitName”, for example “By the carat”.

Of course, because in single UOM/item mode the UI will not have the UOM list, you won’t be able to see the UOM set in the UI in single UOM mode, but you will be able to get the UOM sets by doing a UnitOfMeasureSetQuery.

SDK support for the UOM feature

The Desktop SDK supports the three steps covered above. For creating and querying UOM sets, the SDK provides the following requests:

For associating UOM sets and items, the item add and mod request messages listed below contain an optional UnitOfMeasureSetRef aggregate that you can use to specify the UOM set applied to the item.

The various Item mod requests also contain a ForceUOMChange boolean that is needed to dismiss the UI user prompt that QuickBooks puts up when you try to modify a UOM setting.

For assigning units of measure to items in transactions, the UnitOfMeasure element, which specifies which of the item’s units of measure is to be used, is available in the following request messages:

Considerations for working with the UOM feature in the SDK

Some additional points to consider when working with UOM in the SDK are listed below.

Determining if the UOM feature is available

An application can access UOM functionality for QuickBooks 2008 or greater versions if the company file being used has UOM enabled.

The PreferencesQuery does not currently indicate whether UOM is enabled or not, so you cannot use that. An alternate method is sending a UnitOfMeasureSetQuery, as shown below:

1
2
3
4
5
6
7
<?xml version="1.0"?>
<?qbxml version="7.0"?>
<QBXML>
    <QBXMLMsgsRq onError="continueOnError">
        <UnitOfMeasureSetQueryRq requestID="0" />
    </QBXMLMsgsRq>
</QBXML>

If UOM is not enabled for the company file, the query will return an error code of 3250 “This feature is not enabled or not available in this version of QuickBooks”.

Can I set UOM set defaults for purchase, sales, and shipping?

Yes.

You use the DefaultUnit aggregate in the UnitOfMeasureSetAdd request to specify defaults:

1
2
3
4
<DefaultUnit>
    <UnitUsedFor>Shipping</UnitUsedFor>
    <Unit>box</Unit>
</DefaultUnit>

The <Unit> field can contain any unit specified in the UOM set (base unit or related units).

The <UnitUsedFor> field can contain one of the following values:

  1. Specify a unique name for the UOM set, starting with the prefix “By the”. You’ll get an error code 3100 in the response if the name is not unique.
  2. Create a base unit. See the online help in QuickBooks for an explanation of units of measure and base units and how to pick the base unit.
  3. Optionally, but normally, you’ll create one or more related units using the RelatedUnit aggregate, where you specify the conversion ratio (how many base units are contained in that related unit). For example, if base unit is carton and the related unit “case” contains 10 cartons, then the conversion ratio is 10.
  4. You can also optionally specify which one of the units in the UOM set is to be used as the default unit (via the DefaultUnit aggregate) in transaction lines for purchases, or for sales, or for shipping. The unit specified in a default here will be the unit automatically used in the transaction lines.
  5. Check the response to your UOM set add request to determine whether the company file is enabled for UOM. If this isn’t the case, you’ll get an error code of 3250 in your response, indicating the feature is not supported.
    • Sales
    • Purchase
    • Shipping

If you don’t specify any defaults, the base unit will be used as the default for purchase and sales, and there will be no default for shipping.

See the samples below to see how to set the defaults in QBFC and qbXML.

How do I specify which units the UOM set contains?

You do this by specifying one <BaseUnit>, which is required, and 0 to N <RelatedUnit>, which are all optional, as shown in the following qbxML snippet:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<UnitOfMeasureSetAddRq requestID="0">
    <UnitOfMeasureSetAdd>
        <Name>Munitions</Name>
        <UnitOfMeasureType>Count</UnitOfMeasureType>
        <BaseUnit>
            <Name>cartridge</Name>
            <Abbreviation>ctrdge</Abbreviation>
        </BaseUnit>
        <RelatedUnit>
            <Name>box</Name>
            <Abbreviation>bx</Abbreviation>
            <ConversionRatio>25.00</ConversionRatio>
        </RelatedUnit>
    </UnitOfMeasureSetAdd>
</UnitOfMeasureSetAddRq>
What does the abbreviation field do? Why is it required?

The <Abbreviation> field specified the characters that are to be displayed and printed in the transaction line item if that unit is selected for the item. Without the abbreviation, QuickBooks won’t be able to indicate the unit.

Why do I need to follow the UOM set naming convention?

Every UOM set name should begin with “By the”. For example, “By the pound” or “By the weight”. Why is this? Unless you begin the UOM set with “By the” then the UOM set won’t show up in the UI when the company file is enabled for single UOM per item mode. That is, in the New Item or Edit Item form, the units in those UOM sets won’t appear and you won’t be able to use them in the UI. (However, UOM sets that don’t follow this convention will still show up in a UnitOfMeasureSet query.)

Can I modify a UOM set in the SDK?

No. This is currently not supported.

The UOM workflow in the SDK

You use UnitOfMeasureSetAdd to create a UOM set in the SDK.

Creating UOM sets with the SDK

You use UnitOfMeasureSetAdd to create a UOM set in the SDK.

Example: creating a UOM set in QBFC

The following code sample shows how to build a UOM set. The UOM set name, type, and base unit are required. The sample assigns default units to purchase and sales transaction line items and also for shipping. The sample creates only one related unit.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
SessionManager.OpenConnection "", "IDN UOM Set Add Sample"
SessionManager.BeginSession "", omDontCare
Dim UOM_AddSet As IMsgSetRequest
Set UOM_AddSet = SessionManager.CreateMsgSetRequest("US", 7, 0)

‘Append the add request and get the object so we can set its properties.
Dim UOMSetAdder As IUnitOfMeasureSetAdd
Set UOMSetAdder = UOM_AddSet.AppendUnitOfMeasureSetAddRq

‘Set all required properties UOMSetAdder.UnitOfMeasureType.setValue uomtCount
UOMSetAdder.Name.setValue "By the bale"
UOMSetAdder.BaseUnit.Abbreviation.setValue "ble"
UOMSetAdder.BaseUnit.Name.setValue "bale"

‘Not required, but useful. We set default UOM for purchases, sales, and
‘shipping.
Dim DefUnitList As IDefaultUnit
Set DefUnitList = UOMSetAdder.DefaultUnitList.Append
DefUnitList.Unit.setValue "flake"

‘Specify uufSales to set the unit as default in a Sales txn line item,
‘uufPurchase to set the unit as default in a Purchase txn line item,
‘uufShipping to set a default for a shipping line.
DefUnitList.UnitUsedFor.setValue uufSales

‘Notice we can re-use the IDefaultUnit object.
Set DefUnitList = UOMSetAdder.DefaultUnitList.Append
DefUnitList.Unit.setValue "bale"
DefUnitList.UnitUsedFor.setValue uufPurchase
Set DefUnitList = UOMSetAdder.DefaultUnitList.Append
DefUnitList.Unit.setValue "bale"
DefUnitList.UnitUsedFor.setValue uufShipping

‘Now we specify the other units of measure within the set. You use the
‘conversion ratio field to specify how many base units are contained in the
‘related unit. Here, the conversion ratio is 20 because there are 20 flakes
‘of hay in a bale, which is the base unit.
Dim RelUnit As IRelatedUnit
Set RelUnit = UOMSetAdder.RelatedUnitList.Append
RelUnit.Abbreviation.setValue "flk"
RelUnit.ConversionRatio.setValue 20
RelUnit.Name.setValue "flake"
Example: creating a UOM set in qbXML

The following code sample shows how to build a UOM set. The UOM set name, type, and base unit are required. The sample assigns default units to purchase and sales transaction line items and also for shipping. The sample creates two related units.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?xml version="1.0" ?>
<?qbxml version="7.0"?>
<QBXML>
    <QBXMLMsgsRq onError="stopOnError">
        <UnitOfMeasureSetAddRq requestID="0">
            <UnitOfMeasureSetAdd>
                <Name>By the cartridge</Name>
                <UnitOfMeasureType>Count</UnitOfMeasureType>
                <BaseUnit>
                    <Name>cartridge</Name>
                    <Abbreviation>ctrdge</Abbreviation>
                </BaseUnit>
                <RelatedUnit>
                    <Name>box</Name>
                    <Abbreviation>bx</Abbreviation>
                    <ConversionRatio>25.00</ConversionRatio>
                </RelatedUnit>
                <RelatedUnit>
                    <Name>case</Name>
                    <Abbreviation>cse</Abbreviation>
                    <ConversionRatio>500.00</ConversionRatio>
                </RelatedUnit>
                <DefaultUnit>
                    <UnitUsedFor>Sales</UnitUsedFor>
                    <Unit>box</Unit>
                </DefaultUnit>
                <DefaultUnit>
                    <UnitUsedFor>Purchase</UnitUsedFor>
                    <Unit>case</Unit>
                </DefaultUnit>
                <DefaultUnit>
                    <UnitUsedFor>Shipping</UnitUsedFor>
                    <Unit>box</Unit>
                </DefaultUnit>
            </UnitOfMeasureSetAdd>
        </UnitOfMeasureSetAddRq>
    </QBXMLMsgsRq>
</QBXML>
Applying UOM sets to items

You can specify a UOM set for a service item, inventory item, non-inventory item, item assembly, and item group. You do this by using the UnitOfMeasureSetRef aggregate to refer to an existing UOM set. In an Item* Add request, the UnitOfMeasureSetRef is all you use.

The following code creates a service item with a UOM set specified.

In QBFC

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
SessionManager.OpenConnection "", "IDN ItemService Add Sample"
SessionManager.BeginSession "", omDontCare
Dim ItemServiceAddSet As IMsgSetRequest
Set ItemServiceAddSet = SessionManager.CreateMsgSetRequest("US", 7, 0)
Dim ServiceItemAdder As IItemServiceAdd
Set ServiceItemAdder = ItemServiceAddSet.AppendItemServiceAddRq ServiceItemAdder.Name.setValue "Pump Repair"
ServiceItemAdder.ORSalesPurchase.SalesOrPurchase.Desc.setValue "repair small pumps"
ServiceItemAdder.ORSalesPurchase.SalesOrPurchase.ORPrice.Price.setValue 50
ServiceItemAdder.ORSalesPurchase.SalesOrPurchase.AccountRef.FullName. setValue "Service Income"
ServiceItemAdder.UnitOfMeasureSetRef.FullName.setValue "By the hour"
In qbXML

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" ?>
<?qbxml version="7.0"?>
<QBXML>
  <QBXMLMsgsRq onError="stopOnError">
    <ItemServiceAddRq requestID="0">
      <ItemServiceAdd>
        <Name>Pump Repair</Name>
        <UnitOfMeasureSetRef>
          <FullName>By the hour</FullName>
        </UnitOfMeasureSetRef>
        <SalesOrPurchase>
          <Desc>repair small pumps</Desc>
          <Price>50.00</Price>
          <AccountRef>
            <FullName>Service Income</FullName>
          </AccountRef>
        </SalesOrPurchase>
      </ItemServiceAdd>
    </ItemServiceAddRq>
  </QBXMLMsgsRq>
</QBXML>

In an Item* Mod request, you also need to use the ForceUOMChange if you are changing the UOM set and the base unit of the new set doesn’t match the base unit of the UOM set currently assigned to the item. This does the same thing as the user accepting the warning prompt in the UI. If you don’t specify ForceUOMChange, the default is false, and you’ll get an error if you try to change the UOM set if the new set has a different base unit.

You should be aware that if you change the base unit for an item, you should also change the item’s quantities on hand and cost to reflect the new unit; otherwise the values will be inaccurate. An alternative to handle such UOM changes to an item is to create a new item with the desired UOM set and inactivate the old item.

The following code modifies a service item to change the UOM set.

In QBFC

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
SessionManager.OpenConnection "", "IDN ItemService Mod Sample"
SessionManager.BeginSession "", omDontCare
Dim ItemServiceAddSet As IMsgSetRequest
Set ItemServiceAddSet = SessionManager.CreateMsgSetRequest("US", 7, 0)
Dim ServiceItemAdder As IItemServiceMod
Set ServiceItemAdder = ItemServiceAddSet.AppendItemServiceModRq
ServiceItemAdder.EditSequence.setValue "1197702697"
ServiceItemAdder.ListID.setValue "80000057-1197702697"
ServiceItemAdder.UnitOfMeasureSetRef.FullName.setValue "by the day"
ServiceItemAdder.ForceUOMChange.setValue True
In qbXML

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<?xml version="1.0" ?>
<?qbxml version="7.0"?>
<QBXML>
    <QBXMLMsgsRq onError="stopOnError">
        <ItemServiceModRq requestID="0">
            <ItemServiceMod>
                <ListID>80000057-1197702697</ListID>
                <EditSequence>1197702697</EditSequence>
                <UnitOfMeasureSetRef>
                    <FullName>by the day</FullName>
                </UnitOfMeasureSetRef>
                <ForceUOMChange>1</ForceUOMChange>
            </ItemServiceMod>
        </ItemServiceModRq>
    </QBXMLMsgsRq>
</QBXML>
Using UOM in a transaction add request

When you create or modify a transaction, you specify the UOM in the transaction line item using the UnitOfMeasure element, which occurs after the Quantity element.You must specify a unit from the UOM set for the item that is referenced in that line. Otherwise, you’ll get a runtime error.

Also, the quantity field always reflects the quantity in terms of the base unit. Suppose your base unit is one dozen (eggs). If you order a quantity of 3 and set the units to the related unit of crate (a crate having 10 dozen eggs), then QuickBooks automatically recalculates the quantity to a value of 0.3 because the order now uses the unit crate! It does this calculation using the conversion ratio of that related unit.

The following code creates a SalesOrder containing one line item of “eggs” with a UOM set to “crate”, which contains 10 dozen eggs. Because the base unit is one dozen eggs, the quantity here means 3 dozen eggs, not 3 crates. QuickBooks sees the unit of crate and automatically changes that quantity to reflect the crates unit: 3 dozen eggs becomes 0.3 crates and so the actual SalesOrder is for 0.3 crates of eggs.

In QBFC

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
Dim SessionManager As QBSessionManager
Set SessionManager = New QBSessionManager
SessionManager.OpenConnection2 appID, appleName, ctLocalQBD
SessionManager.BeginSession "", omDontCare
Dim SalesOrderSet As IMsgSetRequest
Set SalesOrderSet = SessionManager.CreateMsgSetRequest("US", 7, 0)
Dim salesOrder As ISalesOrderAdd
Set salesOrder = SalesOrderSet.AppendSalesOrderAddRq
salesOrder.CustomerRef.FullName.setValue "Abercrombie, Kristy"
salesOrder.RefNumber.setValue "121345"
Dim SOLineItemAdder As ISalesOrderLineAdd
Set SOLineItemAdder = salesOrder.ORSalesOrderLineAddList.Append.SalesOrderLineAdd
SOLineItemAdder.ItemRef.FullName.setValue "eggs"
SOLineItemAdder.Quantity.setValue 3
SOLineItemAdder.UnitOfMeasure.setValue "crate"
In qbXML

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" ?>
<?qbxml version="7.0"?>
<QBXML>
    <QBXMLMsgsRq onError = "stopOnError">
        <SalesOrderAddRq requestID = "0">
            <SalesOrderAdd>
                <CustomerRef>
                    <FullName>Abercrombie, Kristy</FullName>
                </CustomerRef>
                <RefNumber>121345</RefNumber>
                <SalesOrderLineAdd>
                    <ItemRef>
                        <FullName>eggs</FullName>
                    </ItemRef>
                    <Quantity>3</Quantity>
                    <UnitOfMeasure>crate</UnitOfMeasure>
                </SalesOrderLineAdd>
            </SalesOrderAdd>
        </SalesOrderAddRq>
    </QBXMLMsgsRq>
</QBXML>
Using UOM in a transaction mod request

When you modify a transaction line to change the unit of measure used in that line, (a unit of measure, NOT the UOM set itself!!), you use the OverrideUOMSetRef aggregate to specify the UOM set that is already specified for the item referenced in that transaction line, and then specify the desired unit within that set.

The name of this aggregate is slightly unfortunate since it might lead you to believe that you can change the UOM set itself here to whatever you want. That is not possible! When you change the UOM in a transaction Mod request, you cannot change the UOM set itself! You can only change to a different unit within the UOM set already specified for the item. You’ll get an error code of 3210 if you try to change the UOM set.

The following code modifies a SalesOrder containing one line item of “eggs” that has a UOM set to “crate”. It changes the quantity from 3 to 4 and changes the unit to “dozen”.

In QBFC

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
Dim SessionManager As QBSessionManager
Set SessionManager = New QBSessionManager
SessionManager.OpenConnection2 appID, appleName, ctLocalQBD
SessionManager.BeginSession "", omDontCare

Dim SalesOrderSet As IMsgSetRequest
Set SalesOrderSet = SessionManager.CreateMsgSetRequest("US", 7, 0)
Dim salesOrder As ISalesOrderMod
Set salesOrder = SalesOrderSet.AppendSalesOrderModRq
salesOrder.EditSequence.setValue "1197739296"
salesOrder.TxnID.setValue "5C56-1197739296"
Dim SOLineItemMod As ISalesOrderLineMod
Set SOLineItemMod = salesOrder.ORSalesOrderLineModList.Append.SalesOrderLineMod
SOLineItemMod.TxnLineID.setValue "5C58-1197739296"
SOLineItemMod.ItemRef.FullName.setValue "eggs"
SOLineItemMod.Quantity.setValue 4

‘We aren’t changing the UOM set here! Just specifying the UOM set ‘already specified for “eggs”!
SOLineItemMod.OverrideUOMSetRef.FullName.setValue "by the dozen"
SOLineItemMod.UnitOfMeasure.setValue "dozen"
In qbXML

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" ?>
<?qbxml version="7.0"?>
<QBXML>
    <QBXMLMsgsRq onError = "stopOnError">
        <SalesOrderModRq requestID = "0">
            <SalesOrderMod>
                <TxnID>5C56-1197739296</TxnID>
                <EditSequence>1197739296</EditSequence>
                <SalesOrderLineMod>
                    <TxnLineID>5C58-1197739296</TxnLineID>
                    <ItemRef>
                        <FullName>eggs</FullName>
                    </ItemRef>
                    <Quantity>4</Quantity>
                    <UnitOfMeasure>dozen</UnitOfMeasure>
                    <OverrideUOMSetRef>
                        <FullName>by the dozen</FullName>
                    </OverrideUOMSetRef>
                </SalesOrderLineMod>
            </SalesOrderMod>
        </SalesOrderModRq>
    </QBXMLMsgsRq>
</QBXML>