(This is my first post - please forgive/straighten me out on any protocol faux pas)
Some issues that I see (in addition to those already pointed out) are:
You cannot (or at least I could not) set an xLineAdd object (e.g. IInvoiceLineAdd, IEstimateLineAdd) to an xLineRet object (e.g. IInvoiceLineRet, IEstimateLineRet) - when you look at the underlying xml it makes sense that you would not be able to.
the xLineAdd object (e.g. IInvoiceLineAdd, IEstimateLineAdd) does not have the TxnLineID property. The xLineMod (e.g. IInvoiceLineMod, IEstimateLineMod) does support the TxnLineID property.
Another issue to be aware of when adding (or modifying) lines to an existing transaction (e.g. Invoice, Estimate) is that you need to specify by TxnLineID all the existing lines that you want to keep after the line add/mod process. Otherwise, all lines that are not explicitly specified in this manner are deleted from the transaction during the modification process.
From the QBSDK Programmers Guide:
"In a Mod request, you can add a new line by supplying a TxnLineID
value of -1. Remember: if you modify any line item, you need to
specify all of the other line items or else they will be dropped as a
result of the Mod. However, you need not fully specify the line item
with all its ItemRef, Quantity, and other elements. You need only
specify its TxnLineID as follows:
<PurchaseOrderLineMod>
<TxnLineID>101</TxnLineID>
</PurchaseOrderLineMod>
This will retain the line item exactly as it was prior to the Mod."
Here is some code I have for adding a line to an existing estimate (should be the same basic concept for adding invoices).
Sub AddLine()
Dim SessMgr As New QBSessionManager
Dim MsgReqObj As IMsgSetRequest
Set MsgReqObj = SessMgr.CreateMsgSetRequest("US", 13, 0)
Dim EstimateModObj As IEstimateMod
Dim ExistingEstimateObj As IEstimateRet
Set EstimateModObj = MsgReqObj.AppendEstimateModRq
Set ExistingEstimateObj = GetEstimateByRef("12") 'function that takes a Reference Number and returns an IEstimateRet object corresponding existing estimate (not included here).
EstimateModObj.TxnID.SetValue ExistingEstimateObj.TxnID.GetValue
EstimateModObj.EditSequence.SetValue ExistingEstimateObj.EditSequence.GetValue
'loop thru line items on existing transaction and add TxnLineIDs to the Mod Object (so they don't get deleted).
For i = 0 To ExistingEstimateObj.OREstimateLineRetList.Count - 1
EstimateModObj.OREstimateLineModList.Append.EstimateLineMod.TxnLineID.SetValue _
ExistingEstimateObj.OREstimateLineRetList.GetAt(i).EstimateLineRet.TxnLineID.GetValue
Next
Dim EstLineAdd As IEstimateLineMod
Set EstLineAdd = EstimateModObj.OREstimateLineModList.Append.EstimateLineMod
EstLineAdd.TxnLineID.SetValue "-1"
EstLineAdd.ItemRef.FullName.SetValue "Drywall - cost"
EstLineAdd.ORRate.Rate.SetValue "150"
SessMgr.OpenConnection "", "GetVendorTest"
SessMgr.BeginSession "", omDontCare
Set MsgRespObj = SessMgr.DoRequests(MsgReqObj)
SessMgr.EndSession
SessMgr.CloseConnection
End Sub