Member Login

Username
Password
Forget Password
New Sign Up
Search Forum

Buy Support
Incidents

If you can't find your answer in the FREE PUBLIC QDeveloper Forum, require URGENT Priority Support, or you need to send us private or confidential information:

Click Here
If you can't login and post questions or you are having trouble viewing forum posts:
Click Here
Callback
Support

If you live in USA, UK, Canada, Australia or New Zealand, you can leave us details on your question and request us to call you back and discuss them with you personally  (charges apply).

Click Here
 
Buy Support
Incidents
If you can't find your answer in the FREE PUBLIC QDeveloper Forum, require URGENT Priority Support, or you need to send us private or confidential information:
Click Here

Forum : Speed up PriceLevelPerItem Access 2007 Append OperationSearch Forum

Forum Home > QODBC - ODBC Driver for QuickBooks > QODBC v9 Forum

 New Topic 
 
 Post Reply 
[1]  
 Speed up PriceLevelPerItem Access 2007 Append Operation 
 Author   Message 
  Daniel Bright 
  
 Group: Members 
 Posts: 5 
 Joined: 2008-12-18 
 Profile
 Posted : 2008-12-18 06:28:16

Hello,

I am not familiar with VB programming, however I am familiar with SQL commands and database operations in general. I have a company file with over 4000 items in QB. I have 3 price levels per item, and when I use Access 2007 to perform an "Append" to the PriceLevelPerItem DB, it takes forever (over 4 hours and it only updated 1200 items). I have read threads that discuss the use of the "batching" of the queries, however as I said before I'm not a VB programmer so I'm not sure how to implement this. I have a table with 10000 Price Levels and it will be updated on a fairly regular basis, is there a way to call the batching command from a SQL statement? Or am I going to have to have some sort of VB programming? Or is there an option that I'm not aware of with the QODBC connector that turns on/off batching? Any help will be greatly appreciated!

 

  Top 
  Tom 
  6c3c1_sdk-qodbc.gif
 Group: Administrator 
 Posts: 5510 
 Joined: 2006-02-17 
 Profile
 Posted : 2008-12-18 09:50:50

You really need to step back here. First of all, there's no database here. QODBC converts SQL statements that are sent to QuickBooks as an XML Request and QuickBooks returns an XML document that QODBC strips off all the tags and gives you the data. If that isn't bad enough, the Intuit engineers also decided that when it comes to the PriceLevelPerItem table (only this table) that the Intuit qbXML SDK also requires the whole table to be exported and then re-imported again. So for multiple operations this gets real slow...... because QuickBooks doesn't append here!!!!

See also:
PriceLevelPerItem Updates & Inserts 
Speeding up PriceLevelPerItem INSERTS? 

 

  Top 
  Daniel Bright 
  
 Group: Members 
 Posts: 5 
 Joined: 2008-12-18 
 Profile
 Posted : 2008-12-18 10:09:38
Tom,

Thanks so much for the quick response, I understand that QODBC is a SQL "translator" and that it is limited by the QB SDK itself. And I have definately read the links that you put up multiple times. What I am hoping to find out is that there is a way to use the "sp_batchstart" and "sp_batchupdate" stored procedure within MS Access, so that I can update 500 records at a time as Paul and Flash were able to do on the second link you listed. And what I'm not sure about is if this is something that I can do by taking a script and simply modifying it to match my needs, or if it is something I would have to have the programmers at QODBC do for me. I was able to get the sp_batchstart/update command working in the VB Demo program, however I'm just not sure how to get this working within Access. Your direction is most appreciated. 

  Top 
  Tom 
  6c3c1_sdk-qodbc.gif
 Group: Administrator 
 Posts: 5510 
 Joined: 2006-02-17 
 Profile
 Posted : 2008-12-18 11:09:46

SP_BATCHSTART PriceLevelPerItem  and SP_BATCHUPDATE PriceLevelPerItem can be run using MS Access SQL Pass-Through Queries as per: How do I create a Pass-Through Report using Microsoft Access 2003?  

 

  Top 
  Daniel Bright 
  
 Group: Members 
 Posts: 5 
 Joined: 2008-12-18 
 Profile
 Posted : 2008-12-18 11:19:35
Tom,

Thanks yet again for the prompt response, it is much appreciated. I understand that to pass the start and update commands I must use pass-through mode, the question I have now is how would I tie this into a VB script to allow it to perform this task in these steps:

  1. Call SP_BATCHSTART
  2. Read the first 500 records from an Excel spreadsheet into the batch
  3. Insert these 500 records into the table
  4. Call SP_BATCHUPDATE
  5. Read the next 500 records from an Excel spreadsheet into the batch
  6. loop until End of File
I've seen some sample code for Visual FoxPro, however none for VBScript, if there is a VBScript code snippet out there that I can put into my own VB Module and manipulate it to work for me that would be great, however it seems that the only way to do this is going to be to pay someone to program it for me (which really sucks because this is the main reason I purchased QODBC in the first place :/, however it is very usefull in other areas as well). Please let me know what I can do in that respect.

Thanks again 

  Top 
  Tom 
  6c3c1_sdk-qodbc.gif
 Group: Administrator 
 Posts: 5510 
 Joined: 2006-02-17 
 Profile
 Posted : 2008-12-18 13:13:31

Here's a MS Access example Sub-procedure a developer sent to me on how they created invoices. You can modify it to build your own for PriceLevel update:

Private Sub Send_Orders_QB_INS(iLogNum As Integer)

    On Error GoTo ERR_SEND
   
    Dim sSQL_OrderHeaders As String
    Dim sSQL_OrderLabor As String
    Dim sSQL_OrderMaterial As String
    Dim sSQL As String

    Dim rsOrder_Headers As Recordset
    Dim rsOrder_Labor As Recordset
    Dim rsOrder_Material As Recordset
   
    Dim sLocalCustName As String
    Dim sQBCustomerID As String
    Dim sQBTermsID As Variant
    Dim sQBItemTaxID As Variant
    Dim sQBCustTaxID As Variant
    Dim sQBCustAddr1 As Variant
    Dim sQBCustAddr2 As Variant
    Dim sQBCustCity As Variant
    Dim sQBCustState As Variant
    Dim sQBCustZip As Variant
    Dim iLaborRowCount As Integer
    Dim iMaterialsRowCount As Integer
   
    Dim sSQL_INVOICE_LINE_INSERT As String
    Dim sSQL_INVOICE_INSERT As String
   
    Dim sCustomerRefListID As String
    Dim sCustomerRefFullName As String
    Dim sClassRefListID As String
    Dim sClassRefFullName As String
    Dim sARAccountRefListID As String
    Dim sARAccountRefFullName As String
    Dim sTxnDate As String
    Dim sRefNumber As String
    Dim sBillAddressAddr1 As String
    Dim sBillAddressAddr2 As String
    Dim sBillAddressCity As String
    Dim sBillAddressState As String
    Dim sBillAddressPostalCode As String
    Dim sTermsRefListID As String
    Dim sTermsRefFullName As String
    Dim sDueDate As String
    Dim sShipDate As String
    Dim sItemSalesTaxRefListID As String
    Dim sItemSalesTaxRefFullName As String
    Dim sCustomerMsgRefListID As String
    Dim sCustomerMsgRefFullName As String
    Dim sCustomerSalesTaxCodeRefListID As String
    Dim sCustomerSalesTax As String
    Dim sCodeRefFullName As String
    Dim sInvoiceLineItemRefListID As String
    Dim sInvoiceLineDesc As String
    Dim dInvoiceLineQuantity As Double
    Dim cInvoiceLineAmount As Currency
    Dim cInvoiceLineRate As Currency
    Dim sInvoiceLineSalesTaxCodeRefListID As String
    Dim sInvoiceLineSalesTaxCodeRefFullName As String
   
    Dim iServiceOrderMatchCnt As Integer
    Dim bDupError As Boolean
   
    DoCmd.SetWarnings False
   
    ' ***** ADDED 05/31/2004 *******************
    ' only allow orders that have an invoice number
    sSQL_OrderHeaders = "SELECT dtl.* FROM dtlServiceOrder AS dtl, tblQB_Exports_Detail_Log AS log " + _
                         "WHERE dtl.ServiceOrderNumber = log.ServiceOrderNumber AND dtl.ServiceOrderStatus = 'Complete' AND log.IsSendable = True AND log.ExportLogNum = " + CStr(iLogNum)
  
    Set rsOrder_Headers = CurrentDb.OpenRecordset(sSQL_OrderHeaders)
      
    Do While Not rsOrder_Headers.EOF
        ' add labor lines to QB Invoice Line table
        iLaborRowCount = 0
        ' ***** ADDED 05/31/2004 *******************
        ' only allow lines that have labor hours included. This is to prevent the import of blank lines.
        sSQL_OrderLabor = "SELECT * FROM dtlServiceOrderLbr WHERE ServiceOrderNumber = '" + rsOrder_Headers!ServiceOrderNumber + "' AND (LbrHoursRG > 0 OR LbrHoursOT > 0 OR LbrHoursDT > 0)"
        Set rsOrder_Labor = CurrentDb.OpenRecordset(sSQL_OrderLabor)
        Do While Not rsOrder_Labor.EOF
            sInvoiceLineItemRefListID = id_INVOICE_LINE_ITEM_REF_Labor
            sInvoiceLineDesc = "Labor"
            dInvoiceLineQuantity = rsOrder_Labor!LbrHoursRG + rsOrder_Labor!LbrHoursOT + rsOrder_Labor!LbrHoursDT
            cInvoiceLineAmount = rsOrder_Labor!LbrTotalCost
            If cInvoiceLineAmount = 0 And dInvoiceLineQuantity = 0 Then
                cInvoiceLineRate = 0
            Else
                cInvoiceLineRate = cInvoiceLineAmount / dInvoiceLineQuantity
            End If
            sInvoiceLineSalesTaxCodeRefListID = id_INVOICE_LINE_SALES_TAX_CODE_Non
            sInvoiceLineSalesTaxCodeRefFullName = "Non"
            sFQSaveToCache = 1
           
            sSQL_INVOICE_LINE_INSERT = "INSERT INTO QB_INVOICE_LINE " + _
                                            "(InvoiceLineItemRefListID,InvoiceLineDesc,InvoiceLineQuantity," + _
                                             "InvoiceLineAmount,InvoiceLineRate,InvoiceLineSalesTaxCodeRefListID," + _
                                             "InvoiceLineSalesTaxCodeRefFullName,FQSaveToCache) " + _
                                       "VALUES " + _
                                            "('" + sInvoiceLineItemRefListID + "','" + sInvoiceLineDesc + "'," + CStr(dInvoiceLineQuantity) + "," + _
                                             "" + CStr(cInvoiceLineAmount) + "," + CStr(cInvoiceLineRate) + ",'" + sInvoiceLineSalesTaxCodeRefListID + "'," + _
                                             "'" + sInvoiceLineSalesTaxCodeRefFullName + "'," + CStr(1) + ")"
           
            CurrentDb.Execute sSQL_INVOICE_LINE_INSERT
           
            iLaborRowCount = iLaborRowCount + 1
           
            rsOrder_Labor.MoveNext
        Loop
   
        ' add material lines to QB Invoice Line table
        iMaterialsRowCount = 0
        ' ***** ADDED 05/31/2004 *******************
        ' only allow lines that have material quantities included. This is to prevent the import of blank lines.
        sSQL_OrderMaterial = "SELECT * FROM dtlServiceOrderMtl WHERE ServiceOrderNumber = '" + rsOrder_Headers!ServiceOrderNumber + "' AND MtlQuantity > 0"
        Set rsOrder_Material = CurrentDb.OpenRecordset(sSQL_OrderMaterial)
        Do While Not rsOrder_Material.EOF
            sInvoiceLineItemRefListID = id_INVOICE_LINE_ITEM_REF_Misc
            sInvoiceLineDesc = rsOrder_Material!MtlItemDescription
            dInvoiceLineQuantity = rsOrder_Material!MtlQuantity
            cInvoiceLineAmount = rsOrder_Material!MtlPrice
            cInvoiceLineRate = rsOrder_Material!MtlExtend
            If (rsOrder_Material!MtlTaxable) = True Or (rsOrder_Material!MtlTaxable2 = True) Then
                sInvoiceLineSalesTaxCodeRefListID = id_INVOICE_LINE_SALES_TAX_CODE_Tax
                sInvoiceLineSalesTaxCodeRefFullName = "Tax"
            Else
                sInvoiceLineSalesTaxCodeRefListID = id_INVOICE_LINE_SALES_TAX_CODE_Non
                sInvoiceLineSalesTaxCodeRefFullName = "Non"
            End If
           
            sSQL_INVOICE_LINE_INSERT = "INSERT INTO QB_INVOICE_LINE " + _
                                            "(InvoiceLineItemRefListID,InvoiceLineDesc,InvoiceLineQuantity," + _
                                             "InvoiceLineAmount,InvoiceLineRate,InvoiceLineSalesTaxCodeRefListID," + _
                                             "InvoiceLineSalesTaxCodeRefFullName,FQSaveToCache) " + _
                                       "VALUES " + _
                                            "('" + sInvoiceLineItemRefListID + "','" + sInvoiceLineDesc + "'," + CStr(dInvoiceLineQuantity) + "," + _
                                             "" + CStr(cInvoiceLineAmount) + "," + CStr(cInvoiceLineRate) + ",'" + sInvoiceLineSalesTaxCodeRefListID + "'," + _
                                             "'" + sInvoiceLineSalesTaxCodeRefFullName + "'," + CStr(1) + ")"
           
            CurrentDb.Execute sSQL_INVOICE_LINE_INSERT
           
            iMaterialsRowCount = iMaterialsRowCount + 1

            rsOrder_Material.MoveNext
        Loop
       
        ' add record to QB Invoice table
        sLocalCustName = DLookup("[CustSort]", "mstCustomers", "[CustNumber] = '" + rsOrder_Headers!CustNumber + "'")
        sQBCustomerID = GetCustomerID(rsOrder_Headers!CustNumber, sLocalCustName)
        sCustomerRefListID = sQBCustomerID
        sCustomerRefFullName = sLocalCustName
        sARAccountRefListID = id_ARA_ACCOUNT_REF_Accounts_Receivable
        sARAccountRefFullName = "Accounts Receivable"
        sTxnDate = CStr(rsOrder_Headers!ServiceOrderDate)
        'sRefNumber = GetNextQBRefNum()
        sRefNumber = rsOrder_Headers!ServiceOrderInvNum
        sClassRefListID = id_CLASS_REF_landscaping
        sClassRefListID = id_CLASS_REF_landscaping
        sClassRefFullName = "Commerical Landscaping"
        sQBCustAddr1 = DLookup("[BillAddressAddr1]", "QB_CUSTOMER", "[ListID] = '" + sCustomerRefListID + "'")
        If IsNull(sQBCustAddr1) Then
            sBillAddressAddr1 = ""
        Else
            sBillAddressAddr1 = sQBCustAddr1
        End If
        sQBCustAddr2 = DLookup("[BillAddressAddr2]", "QB_CUSTOMER", "[ListID] = '" + sCustomerRefListID + "'")
        If IsNull(sQBCustAddr2) Then
            sBillAddressAddr2 = ""
        Else
            sBillAddressAddr2 = sQBCustAddr2
        End If
        sQBCustCity = DLookup("[BillAddressCity]", "QB_CUSTOMER", "[ListID] = '" + sCustomerRefListID + "'")
        If IsNull(sQBCustCity) Then
            sBillAddressCity = ""
        Else
            sBillAddressCity = sQBCustCity
        End If
        sQBCustState = DLookup("[BillAddressState]", "QB_CUSTOMER", "[ListID] = '" + sCustomerRefListID + "'")
        If IsNull(sQBCustState) Then
            sBillAddressState = ""
        Else
            sBillAddressState = sQBCustState
        End If
        sQBCustZip = DLookup("[BillAddressPostalCode]", "QB_CUSTOMER", "[ListID] = '" + sCustomerRefListID + "'")
        If IsNull(sQBCustZip) Then
            sBillAddressPostalCode = ""
        Else
            sBillAddressPostalCode = sQBCustZip
        End If
        sQBTermsID = DLookup("[TermsRefListID]", "QB_CUSTOMER", "[ListID] = '" + sQBCustomerID + "'")
        If IsNull(sQBTermsID) Or (sQBTermsID = "") Then
            sTermsRefListID = id_TERMS_REF_Due_on_receipt
            sTermsRefFullName = "Due on receipt"
        Else
            sTermsRefListID = sQBTermsID
            sTermsRefFullName = DLookup("[TermsRefFullName]", "QB_CUSTOMER", "[ListID] = '" + sQBCustomerID + "'")
        End If
        sDueDate = CStr(rsOrder_Headers!ServiceOrderDate)
        sShipDate = CStr(rsOrder_Headers!ServiceOrderDate)
        sQBItemTaxID = DLookup("[ItemSalesTaxRefListID]", "QB_CUSTOMER", "[ListID] = '" + sQBCustomerID + "'")
        If IsNull(sQBItemTaxID) Or (sQBItemTaxID = "") Then
            sItemSalesTaxRefListID = id_ITEM_SALES_TAX_REF_6
            sItemSalesTaxRefFullName = "6% Sales Tax"
        Else
            sItemSalesTaxRefListID = sQBItemTaxID
            sItemSalesTaxRefFullName = DLookup("[ItemSalesTaxRefFullName]", "QB_CUSTOMER", "[ListID] = '" + sQBCustomerID + "'")
        End If
        sCustomerMsgRefListID = id_CUSTOMER_MSG_REF_Thank_you
        sCustomerMsgRefFullName = " Thank you for your business."
        sQBCustTaxID = DLookup("[SalesTaxCodeRefListID]", "QB_CUSTOMER", "[ListID] = '" + sQBCustomerID + "'")
        If IsNull(sQBItemTaxID) Or (sQBItemTaxID = "") Then
            sCustomerSalesTaxCodeRefListID = id_INVOICE_LINE_SALES_TAX_CODE_Tax
            sCustomerSalesTaxCodeRefFullName = "Tax"
        Else
            sCustomerSalesTaxCodeRefListID = sQBCustTaxID
            sCustomerSalesTaxCodeRefFullName = DLookup("[SalesTaxCodeRefFullName]", "QB_CUSTOMER", "[ListID] = '" + sQBCustomerID + "'")
        End If
       
        sSQL_INVOICE_INSERT = "INSERT INTO QB_INVOICE " + _
                                    "(CustomerRefListID,CustomerRefFullName,ClassRefListID,ClassRefFullName," + _
                                     "ARAccountRefListID,ARAccountRefFullName,TxnDate,RefNumber,BillAddressAddr1," + _
                                     "BillAddressAddr2,BillAddressCity,BillAddressState,BillAddressPostalCode," + _
                                     "IsPending,TermsRefListID,TermsRefFullName,DueDate,ShipDate,ItemSalesTaxRefListID," + _
                                     "ItemSalesTaxRefFullName,CustomerMsgRefListID,CustomerMsgRefFullName,IsToBePrinted," + _
                                     "CustomerSalesTaxCodeRefListID) " + _
                              "VALUES " + _
                                    "('" + sCustomerRefListID + "','" + sCustomerRefFullName + "','" + sClassRefListID + "','" + sClassRefFullName + "'," + _
                                     "'" + sARAccountRefListID + "','" + sARAccountRefFullName + "','" + sTxnDate + "','" + sRefNumber + "','" + sBillAddressAddr1 + "'," + _
                                     "'" + sBillAddressAddr2 + "','" + sBillAddressCity + "','" + sBillAddressState + "','" + sBillAddressPostalCode + "'," + _
                                     "" + CStr(0) + ",'" + sTermsRefListID + "','" + sTermsRefFullName + "','" + sDueDate + "','" + sShipDate + "','" + sItemSalesTaxRefListID + "'," + _
                                     "'" + sItemSalesTaxRefFullName + "','" + sCustomerMsgRefListID + "','" + sCustomerMsgRefFullName + "'," + CStr(0) + "," + _
                                     "'" + sCustomerSalesTaxCodeRefListID + "')"
       
        If (iLaborRowCount + iMaterialsRowCount > 0) Then
            CurrentDb.Execute sSQL_INVOICE_INSERT
       
            If Not bDupError Then
                iOrdersExported = iOrdersExported + 1
            End If
            bDupError = False
        End If
       
        ' ***** ADDED 05/31/2004 *******************
        ' add to detail log
        sSQL = "UPDATE tblQB_Exports_Detail_Log SET OrderSent = 1 WHERE ExportLogNum = " + CStr(iLogNum) + " AND " + _
                                                                       "ServiceOrderNumber = " + MakeString(rsOrder_Headers!ServiceOrderNumber, True)
        CurrentDb.Execute sSQL
       
        ' update status
        sSQL = "UPDATE dtlServiceOrder " + _
                         "SET ServiceOrderStatus = 'Exported', " + _
                             "Export_batch_number = 'QB" + CStr(iLogNum) + "', " + _
                             "Export_date = '" + CStr(Date) + "' " + _
                      "WHERE ServiceOrderNumber = '" + rsOrder_Headers!ServiceOrderNumber + "'"
        CurrentDb.Execute sSQL
       
MOVE_NEXT:
        rsOrder_Headers.MoveNext
    Loop

    DoCmd.SetWarnings True
   
    Exit Sub
   
ERR_SEND:
    Select Case Err.Number
    Case 3155
        MsgBox "Invoice '" + sRefNumber + "' failed." + vbCrLf + "Most likely this Order is already in QuickBooks." + vbCrLf + "Please write down the order number and research it after this process is complete.", vbExclamation
        bDupError = True
        Resume Next
    Case Else
        MsgBox CStr(Err.Number) + "--" + Err.Description
        Exit Sub
    End Select

End Sub

 

  Top 
  Daniel Bright 
  
 Group: Members 
 Posts: 5 
 Joined: 2008-12-18 
 Profile
 Posted : 2008-12-18 13:23:18
Tom,

Thanks for the code, I will definately try and get this to work, I did however already try and go a simpler route, I split up my Excel file into 500 row increments and then imported them into Access, and using the pass-thru mode setup as you suggested, here is the SQL code I have in place:

SP_BATCHSTART PriceLevelPerItem

INSERT INTO PriceLevelPerItem ("ListID", "IsActive", "Name", "PriceLevelPerItemItemRefFullName", "PriceLevelPerItemCustomPrice") SELECT "ListID", "IsActive", "Name", "PriceLevelPerItemItemRefFullName", "PriceLevelPerItemCustomPrice" FROM CONT1;

SP_BATCHUPDATE PriceLevelPerItem

However, it doesn't seem to want to work, I receive an error "Unexpected extra token: INSERT (#11017)" if I'm doing something wrong, or this is simply impossible to get to work this way, then I will dive into that code and see what I can figure out.

Thanks! 

  Top 
  Tom 
  6c3c1_sdk-qodbc.gif
 Group: Administrator 
 Posts: 5510 
 Joined: 2006-02-17 
 Profile
 Posted : 2008-12-18 16:34:19
A pass-through query can only have one SQL statement, not three. 

  Top 
  Daniel Bright 
  
 Group: Members 
 Posts: 5 
 Joined: 2008-12-18 
 Profile
 Posted : 2008-12-18 23:11:22
Tom,

Understood, I took that and ran with it, however when I try to pass the statements one at a time, when I get to the actual SQL statement itself I receive an error: "ODBC --call failed. [QODBC] Invalid table name: CONTDISC (#11025)", I've tried rewriting it several times however I'm not sure what the problem is, syntax:

INSERT INTO PriceLevelPerItem ("ListID", "IsActive", "Name", "PriceLevelPerItemItemRefFullName", "PriceLevelPerItemCustomPrice") SELECT ListID, IsActive, Name, PriceLevelPerItemItemRefFullName, PriceLevelPerItemCustomPrice FROM CONTDISC

Please let me know what you think.
Regards 

  Top 
  Tom 
  6c3c1_sdk-qodbc.gif
 Group: Administrator 
 Posts: 5510 
 Joined: 2006-02-17 
 Profile
 Posted : 2008-12-19 10:50:25
A pass-through query passes the SQL statement directly to QODBC which doesn't have a CONTDISC table. You can't run append queries as pass-through queries.
 

  Top 
 New Topic 
 
 Post Reply 
[1]  

Jump to