Wednesday, 30 July 2008

Third party integration

If you recieve an error "Sage Data Objects is not registered, please contact the supplier of this application" within a day or so of trying the trail version, don't panic, simply activate third party integration as follows:

1. Open Sage and click the Tools | Activation | Enable Third Party Integration menu option.

3. A screen will appear with a phone number to call; request the SDO Serial Number and Activation Key from the Sage customer services agent, enter the details in the textboxes provided and click the Register button.

Note: when calling the phone number the Sage customer services agent will usually ask you for you Sage Line 50 Serial Number (see the Help | About menu for this), your company name, first line of your address and / or postcode. Attaining the SDO Serial Number and Activation Key is a completely free service (apart from the price of the call) and will typically take no long than 5 minutes.

Wednesday, 23 July 2008

Read Purchase orders from Sage in VB.NET

Reading purchase orders from Sage is very similar to reading invoices (sales orders) from sage, but once again, the objects you use are prefixed with "pop" (purchase order processing), and you use a different set of schemas.

Here's the code:

Private Sub btnPurchases_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPurchases.Click
Dim strOrderNumber As String
Dim prPurchase As SageDataObject50.PopRecord = DirectCast(ws50.CreateObject("PopRecord"), SageDataObject50.PopRecord)

While Not prPurchase.IsEOF()
' For A Full list of available fields go to:
' and see the PURCHASE_ORDER Table
strOrderNumber = prPurchase.Fields.Item("ORDER_NUMBER").Value.ToString()
Dim popItem As SageDataObject50.PopItem
popItem = CType(prPurchase.Link, SageDataObject50.PopItem)
' For A Full list of available fields go to:
' and see the POP_ITEM Table
Dim strLineItemText As String
strLineItemText = popItem.Fields.Item("TEXT").Value.ToString()
Loop While popItem.MoveNext()
End While
End Sub

Saturday, 19 July 2008

Post a purchase order in VB.NET

Posting a purchase order in VB.NET is similar to posting an invoice, you're using Pop-prefixed classes rather than Invoice-Prefix classes, and using a different underlying schema, but otherwise, it's more or less the same, here is a code example:
Private Sub btnPurchaseOrderPost_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPurchaseOrderPost.Click
Dim PurchaseOrderRecord As SageDataObject50.PopRecord = ws50.CreateObject("PopRecord")
Dim PurchaseOrderPost As SageDataObject50.PopPost = ws50.CreateObject("PopPost")

'Set the type of invoice so we can find the next available number
'PurchaseOrderPost.Type = SageDataObject50.LedgerType.sdoLedgerService

'Loop for Number of Items on the Invoice
Dim PurchaseOrderItem As SageDataObject50.PopItem = PurchaseOrderPost.Items.Add()

' This is the text for the line

PurchaseOrderItem.Fields.Item("Text").Value = "Invoice Line Text"
PurchaseOrderItem.Fields.Item("Service_Item_Lines").Value = CLng(1)
PurchaseOrderItem.Fields.Item("Net_Amount").Value = CLng(100)
PurchaseOrderItem.Fields.Item("Full_Net_Amount").Value = CLng(100)
PurchaseOrderItem.Fields.Item("Tax_Amount").Value = CLng(0)
PurchaseOrderItem.Fields.Item("Nominal_Code").Value = "4000" 'Sales
PurchaseOrderItem.Fields.Item("Tax_Code").Value = "T9"
PurchaseOrderItem.Fields.Item("Tax_Rate").Value = CDec(0)

'Populate Header Information
' see
' PURCHASE_ORDER for schema
PurchaseOrderPost.Header("Order_Date").value = DateTime.Now.ToString("MM/dd/yyyy")
PurchaseOrderPost.Header("Notes_1").value = "Notes 1"
PurchaseOrderPost.Header("Notes_2").value = ""
PurchaseOrderPost.Header("Notes_3").value = ""
PurchaseOrderPost.Header("Taken_By").value = ""
PurchaseOrderPost.Header("Order_Number").value = ""
PurchaseOrderPost.Header("Payment_Ref").value = ""
PurchaseOrderPost.Header("Global_Nom_Code").value = ""
PurchaseOrderPost.Header("Global_Details").value = ""
PurchaseOrderPost.Header("Items_Net").value = CDec(100)
PurchaseOrderPost.Header("Items_Tax").value = CDec(0)

'Read the first customer
PurchaseOrderPost.Header("Account_Ref").value = CStr(PurchaseOrderRecord.Fields.Item("Account_Ref").Value)
PurchaseOrderPost.Header("Name").value = CStr(PurchaseOrderRecord.Fields.Item("Name").Value)
PurchaseOrderPost.Header("Address_1").value = CStr(PurchaseOrderRecord.Fields.Item("Address_1").Value)
PurchaseOrderPost.Header("Address_2").value = CStr(PurchaseOrderRecord.Fields.Item("Address_2").Value)
PurchaseOrderPost.Header("Address_3").value = CStr(PurchaseOrderRecord.Fields.Item("Address_3").Value)
PurchaseOrderPost.Header("Address_4").value = CStr(PurchaseOrderRecord.Fields.Item("Address_4").Value)
PurchaseOrderPost.Header("Address_5").value = CStr(PurchaseOrderRecord.Fields.Item("Address_5").Value)
PurchaseOrderPost.Header("Del_Address_1").value = CStr(PurchaseOrderRecord.Fields.Item("Del_Address_1").Value)
PurchaseOrderPost.Header("Del_Address_2").value = CStr(PurchaseOrderRecord.Fields.Item("Del_Address_2").Value)
PurchaseOrderPost.Header("Del_Address_3").value = CStr(PurchaseOrderRecord.Fields.Item("Del_Address_3").Value)
PurchaseOrderPost.Header("Del_Address_4").value = CStr(PurchaseOrderRecord.Fields.Item("Del_Address_4").Value)
PurchaseOrderPost.Header("Del_Address_5").value = CStr(PurchaseOrderRecord.Fields.Item("Del_Address_5").Value)
PurchaseOrderPost.Header("Contact_Name").value = CStr(PurchaseOrderRecord.Fields.Item("Contact_Name").Value)

PurchaseOrderPost.Header("Order_Number").value = CLng(101)

If PurchaseOrderPost.Update Then
MessageBox.Show("Purchase Order Created Successfully")
MessageBox.Show("Purchase Order NOT Created")
End If

End Sub

Thursday, 17 July 2008

Posting an Invoice in C#

In many respects the Sage Data Objects library is much easier to use from VB.NET than C#, why?, because VB.NET deals with object casting in a much less strict way. This way, you can say:

InvItem.Fields.Item("Text").Value = "Invoice Line Text"

Rather than

object TEXT = "Text";
InvItem.Fields.Item(ref TEXT).Value = "Invoice Line Text";

Further more, since the internals of Sage hide many implementation details, you may not know what class an object is, since .NET will only report that it's a ComObject, Nothing more.

In most cases, we'd recommend that you create a stub library in VB.NET to host our component, and provide services to your C# Application, however, if that is not possible, then here is how to carry out a common task in sage, - posting an Invoice

public void CreateInvoice(DateTime InvoiceDate, int InvoiceNumber)
SageDataObject50.InvoicePost InvPost;

InvPost = (SageDataObject50.InvoicePost)ws50.CreateObject("InvoicePost");

InvPost.Type =(SageDataObject50.InvoiceType)SageDataObject50.LedgerType.sdoLedgerInvoice;
object Invoice_Number = "Invoice_Number";
object Invoice_Date = "Invoice_Date";

SageDataObject50.IFields ifHeaderFields = null;

Type t = InvPost.Header.GetType();

Object oFields = t.InvokeMember("Fields",
, null, InvPost.Header, new Object[0]);

ifHeaderFields = (SageDataObject50.IFields)oFields;

ifHeaderFields.Item(ref Invoice_Number).Value = InvoiceNumber;
ifHeaderFields.Item(ref Invoice_Date).Value = InvoiceDate.ToString("MM/dd/yyyy");

t = InvPost.Items.GetType();

Object oItem = t.InvokeMember("Add",
new Object[0]);

SageDataObject50.InvoiceItem InvItem;
InvItem = (SageDataObject50.InvoiceItem)oItem;

// This is the text for the line
InvItem.Text = "Description";
object TEXT = "Text";
object SERVICE_ITEM_LINES = "Service_Item_Lines";
object NET_AMOUNT = "Net_Amount";
object FULL_NET_AMOUNT = "Full_Net_Amount";
object TAX_AMOUNT = "Tax_Amount";
object NOMINAL_CODE = "Nominal_Code";
object TAX_CODE = "Tax_Code";
object TAX_RATE = "Tax_Rate";

InvItem.Fields.Item(ref TEXT).Value = "Invoice Line Text";
InvItem.Fields.Item(ref SERVICE_ITEM_LINES).Value = (double)1;
InvItem.Fields.Item(ref NET_AMOUNT).Value = (double)100;
InvItem.Fields.Item(ref FULL_NET_AMOUNT).Value = (double)100;
InvItem.Fields.Item(ref TAX_AMOUNT).Value = (double)0;
InvItem.Fields.Item(ref NOMINAL_CODE).Value = "4000";
InvItem.Fields.Item(ref TAX_CODE).Value = "T9";
InvItem.Fields.Item(ref TAX_RATE).Value = (decimal)0;

if (!InvPost.Update())
MessageBox.Show("Unable to create invoice");
MessageBox.Show("Invoice Created");