Showing posts with label Create Table. Show all posts
Showing posts with label Create Table. Show all posts

Tuesday, 24 April 2007

Deja Vu

I needed to perform the same set of tasks for the Requests folder, which contains tasks items.

I decided to start by doing the SQL Table to hold my items. To assist with this I used MFCMapi, downloadable from:
http://www.microsoft.com/downloads/details.aspx?familyid=55fdffd7-1878-4637-9808-1e21abb3ae37&displaylang=en
This helped me with determining the field names to use in my SQL Table, not that it matters, afterall 'A rose by any other name would smell as sweet' a saying my maths tutor Mr Bunting once used to explain variables!

So my script to create the SQL Table turned out as follows:

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[Requests]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[Time]
GO

CREATE TABLE [dbo].[Requests] (
[GUID] uniqueidentifier ROWGUIDCOL NOT NULL ,
[ID] [int] IDENTITY (1, 1) NOT NULL ,
[URLName] [nvarchar] (256) COLLATE Latin1_General_CI_AS NOT NULL ,
[StoreEntryID] [nvarchar] (160) COLLATE Latin1_General_CI_AS NOT NULL ,
[EntryID] [nvarchar] (160) COLLATE Latin1_General_CI_AS NOT NULL ,
[LoggedBy] [nvarchar] (256) COLLATE Latin1_General_CI_AS NULL ,
[LoggedFor] [nvarchar] (256) COLLATE Latin1_General_CI_AS NULL ,
[Contacts] [nvarchar] (128) COLLATE Latin1_General_CI_AS NULL ,
[Company] [nvarchar] (128) COLLATE Latin1_General_CI_AS NULL ,
[Subject] [nvarchar] (256) COLLATE Latin1_General_CI_AS NOT NULL ,
[Priority] [int] NULL ,
[PurchaseOrderNumber] [nvarchar] (32) COLLATE Latin1_General_CI_AS NOT NULL ,
[RequestID] [nvarchar] (16) COLLATE Latin1_General_CI_AS NULL ,
[Categories] [nvarchar] (128) COLLATE Latin1_General_CI_AS NULL ,
[DueDate] [datetime] NULL ,
[StartDate] [datetime] NULL ,
[CompletedDate] [datetime] NULL ,
[Status] [int] NULL ,
[Owner] [nvarchar] (32) COLLATE Latin1_General_CI_AS NULL ,
[Employees] [nvarchar] (256) COLLATE Latin1_General_CI_AS NULL ,
[TotalWork] [int] NULL ,
[ActualWork] [int] NULL ,
[BillingInformation] [nvarchar] (256) COLLATE Latin1_General_CI_AS NULL ,
[Creator] [nvarchar] (32) COLLATE Latin1_General_CI_AS NULL ,
[CreationTime] [datetime] NULL ,
[LastModifier] [nvarchar] (32) COLLATE Latin1_General_CI_AS NULL ,
[LastModificationTime] [datetime] NULL ,
[Body] [ntext] COLLATE Latin1_General_CI_AS NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

ALTER TABLE [dbo].[Requests] WITH NOCHECK ADD
CONSTRAINT [PK_Requests] PRIMARY KEY CLUSTERED
(
[ID]
) WITH FILLFACTOR = 90 ON [PRIMARY]
GO

ALTER TABLE [dbo].[Requests] ADD
CONSTRAINT [DF_Requests_ID] DEFAULT (newid()) FOR [GUID]
GO


The next step was to create the Stored Procedure to do our saves:


if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[SaveRequest]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[SaveRequest]
GO

SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS OFF
GO


CREATE PROCEDURE SaveRequest
(
@GUID uniqueidentifier=NULL,
@ID int=0,
@URLName nvarchar(256)='',
@StoreEntryID nvarchar (160),
@EntryID nvarchar (160),
@LoggedBy nvarchar (256)=NULL,
@LoggedFor nvarchar (256)=NULL,
@Contacts nvarchar (128)=NULL,
@Company nvarchar (128)=NULL,
@Subject nvarchar (256),
@Priority int=NULL,
@PurchaseOrderNumber nvarchar (32)=NULL,
@RequestID nvarchar (16)=NULL,
@Categories nvarchar (128)=NULL,
@DueDate datetime=NULL,
@StartDate datetime=NULL,
@CompletedDate datetime=NULL,
@Status int=NULL,
@Owner nvarchar (32)=NULL,
@Employees nvarchar (256)=NULL,
@TotalWork int=NULL,
@ActualWork int=NULL,
@BillingInformation nvarchar (256)=NULL,
@Creator nvarchar (32)=NULL,
@CreationTime datetime=NULL,
@LastModifier nvarchar (32)=NULL,
@LastModificationTime datetime=NULL,
@Body ntext=NULL
)
AS

SET NOCOUNT ON

DECLARE
@trncnt int,
@ErrorNumber int

SELECT @ErrorNumber = -1

SELECT @trncnt = @@trancount

IF @trncnt = 0
BEGIN TRANSACTION T1
ELSE
SAVE TRANSACTION T1

IF @EntryID IS NOT NULL
SET @ID = (SELECT ID FROM Requests WHERE EntryID=@EntryID)

IF @ID IS NULL
SET @ID = 0

IF @ID=0 --No ID passed so INSERT
BEGIN

SET @GUID=NEWID()

INSERT INTO Requests
(GUID, URLName, StoreEntryID, EntryID, LoggedBy, LoggedFor, Contacts, Company, Subject, Priority, PurchaseOrderNumber, RequestID, Categories, DueDate, StartDate, CompletedDate, Status, Owner, Employees, TotalWork, ActualWork, BillingInformation, Creator, CreationTime, LastModifier, LastModificationTime, Body)
VALUES
(@GUID, @URLName, @StoreEntryID, @EntryID, @LoggedBy, @LoggedFor, @Contacts, @Company, @Subject, @Priority, @PurchaseOrderNumber, @RequestID, @Categories, @DueDate, @StartDate, @CompletedDate, @Status, @Owner, @Employees, @TotalWork, @ActualWork, @BillingInformation, @Creator, @CreationTime, @LastModifier, @LastModificationTime, @Body)
SET @ID=@@IDENTITY

END
ELSE --ID Passed so UPDATE
BEGIN
UPDATE Requests
SET
URLName=@URLName,
StoreEntryID=@StoreEntryID,
EntryID=@EntryID,
LoggedBy=@LoggedBy,
LoggedFor=@LoggedFor,
Contacts=@Contacts,
Company=@Company,
Subject=@Subject,
Priority=@Priority,
PurchaseOrderNumber=@PurchaseOrderNumber,
RequestID=@RequestID,
Categories=@Categories,
DueDate=@DueDate,
StartDate=@StartDate,
CompletedDate=@CompletedDate,
Status=@Status,
Owner=@Owner,
Employees=@Employees,
TotalWork=@TotalWork,
ActualWork=@ActualWork,
BillingInformation=@BillingInformation,
Creator=@Creator,
CreationTime=@CreationTime,
LastModifier=@LastModifier,
LastModificationTime=@LastModificationTime,
Body=@Body
WHERE (ID=@ID)
END

SELECT @ID

IF @@Error <> 0 GOTO ErrorHandler

IF @trncnt = 0
COMMIT TRANSACTION

RETURN (0)

ErrorHandler:
ROLLBACK TRANSACTION
RETURN (100)

GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO


The next step was to alter my existing TimeItem.vbs script to cope with receiving a request and then saving it to the DB, this is the script I ended up with (although at some point I'll probablt tidy up and create one script for both Time and Requests):


' VBScript File
Set obArgs = WScript.Arguments
Action = lcase(obArgs.Item(0))
itemURL = lcase(obArgs.Item(1))

If obArgs.Count=3 Then
EntryID = obArgs.Item(2)
End If

providerURL = "file://./backofficestorage/ctscomputing.com/Public Folders/"
connectionString = "Provider=SQLOLEDB;Data Source=ctsnts01;Initial Catalog=Exchange;User ID=sa;Password=************"

Dim GUID, ID, URLName, StoreEntryID, EntryID, LoggedBy, LoggedFor, Contacts, Company, Subject, Priority, PurchaseOrderNumber, RequestID, Categories, DueDate, StartDate, CompletedDate, Status, Owner, Employees, TotalWork, ActualWork, BillingInformation, Creator, CreationTime, LastModifier, LastModificationTime, Body

Select Case Action
Case "save"
GetJournalItem itemURL
SaveRequest GUID, ID, URLName, StoreEntryID, EntryID, LoggedBy, LoggedFor, Contacts, Company, Subject, Priority, PurchaseOrderNumber, RequestID, Categories, DueDate, StartDate, CompletedDate, Status, Owner, Employees, TotalWork, ActualWork, BillingInformation, Creator, CreationTime, LastModifier, LastModificationTime, Body
DebugScript

Case "delete"
EntryID=GetEntryID(itemURL)
If Len(EntryID)>0 Then
DeleteRequest EntryID
DebugScript
End If
End Select
'DebugVariables

Sub GetJournalItem(bstrURL)
On Error Resume Next

If Len(EntryID)=0 Then
EntryID = GetEntryID(bstrURL)
End If

'Log on via CDO 1.21.
Set objSession = CreateObject("MAPI.Session")
objSession.Logon "", "", False, True, 0, True, "CTSNTS01" & vbLf & "Administrator"

'Get the message based on the message entry ID.
Set objpubstore = objSession.InfoStores("Public Folders")
Set objMsg = objSession.GetMessage(EntryID,objpubStore.id)

URLName=objMsg.Fields(&H6707001E).Value

StoreEntryID=objMsg.Fields(&H0FFB0102).Value

EntryID=objMsg.Fields(&H0FFF0102).Value

LoggedBy=objMsg.Fields(&H82E0001E).Value

LoggedFor=objMsg.Fields(&H82DF001E).Value

MultiValue=objMsg.Fields(&H819B101E)
Contacts=Join(MultiValue, ";")

MultiValue=objMsg.Fields(&H813A101E)
Company=Join(MultiValue, ";")

Subject=objMsg.Fields(&H0037001E).Value

Priority=objMsg.Fields(&H00260003).Value

PurchaseOrderNumber=objMsg.Fields(&H82DE001E).Value

RequestID=objMsg.Fields(&H82E2001E).Value

MultiValue=objMsg.Fields(&H80DB101E).Value
Categories=Join(MultiValue, ";")

DueDate=objMsg.Fields(&H811F0040).Value

StartDate=objMsg.Fields(&H811E0040).Value

CompletedDate=objMsg.Fields(&H81250040).Value

Status=objMsg.Fields(&H81200003).Value

Owner=objMsg.Fields(&H82FC001E).Value

MultiValue=objMsg.Fields(&H82E1101E)
Employees=Join(MultiValue, ";")

TotalWork=objMsg.Fields(&H81290003).Value

ActualWork=objMsg.Fields(&H81280003).Value

BillingInformation=objMsg.Fields(&H808B001E).Value

Creator=objMsg.Fields(&H3FF8001E).Value

CreationTime=objMsg.Fields(&H30070040).Value

LastModifier=objMsg.Fields(&H3FFA001E).Value

LastModificationTime=objMsg.Fields(&H30080040).Value

Body=objMsg.Fields(&H1000000A).Value

Set objMsg = Nothing

objSession.Logoff
Set objSession = Nothing
'If Err.Number<>0 Then DebugError "GetJournalItem Error:" & Err.Number & ":" & Err.Description
End Sub

Function SaveRequest(GUID, ID, URLName, StoreEntryID, EntryID, LoggedBy, LoggedFor, Contacts, Company, Subject, Priority, PurchaseOrderNumber, RequestID, Categories, DueDate, StartDate, CompletedDate, Status, Owner, Employees, TotalWork, ActualWork, BillingInformation, Creator, CreationTime, LastModifier, LastModificationTime, Body)
On Error Resume Next

Dim Conn,Rec,strSQL
Set Conn = CreateObject("ADODB.Connection")
Set Rec = CreateObject("ADODB.Record")

Conn.ConnectionString = connectionString
Conn.Open

strSQL="Exec SaveRequest "
strSQL=strSQL & "@URLName='" & ConvertSQLDataType("nvarchar", URLName) & "', "
strSQL=strSQL & "@StoreEntryID='" & ConvertSQLDataType("nvarchar", StoreEntryID) & "', "
strSQL=strSQL & "@EntryID='" & ConvertSQLDataType("nvarchar", EntryID) & "', "
strSQL=strSQL & "@LoggedBy='" & ConvertSQLDataType("nvarchar", LoggedBy) & "', "
strSQL=strSQL & "@LoggedFor='" & ConvertSQLDataType("nvarchar", LoggedFor) & "', "
strSQL=strSQL & "@Contacts='" & ConvertSQLDataType("nvarchar", Contacts) & "', "
strSQL=strSQL & "@Company='" & ConvertSQLDataType("nvarchar", Company) & "', "
strSQL=strSQL & "@Subject='" & ConvertSQLDataType("nvarchar", Subject) & "', "
strSQL=strSQL & "@Priority=" & ConvertSQLDataType("int", Priority) & ", "
strSQL=strSQL & "@PurchaseOrderNumber='" & ConvertSQLDataType("nvarchar", PurchaseOrderNumber) & "', "
strSQL=strSQL & "@RequestID='" & ConvertSQLDataType("nvarchar", RequestID) & "', "
strSQL=strSQL & "@Categories='" & ConvertSQLDataType("nvarchar", Categories) & "', "
strSQL=strSQL & "@DueDate=" & ConvertSQLDataType("datetime", DueDate) & ", "
strSQL=strSQL & "@StartDate=" & ConvertSQLDataType("datetime", StartDate) & ", "
strSQL=strSQL & "@CompletedDate=" & ConvertSQLDataType("datetime", CompletedDate) & ", "
strSQL=strSQL & "@Status=" & ConvertSQLDataType("int", Status) & ", "
strSQL=strSQL & "@Owner='" & ConvertSQLDataType("nvarchar", Owner) & "', "
strSQL=strSQL & "@Employees='" & ConvertSQLDataType("nvarchar", Employees) & "', "
strSQL=strSQL & "@TotalWork=" & ConvertSQLDataType("int", TotalWork) & ", "
strSQL=strSQL & "@ActualWork=" & ConvertSQLDataType("int", ActualWork) & ", "
strSQL=strSQL & "@BillingInformation='" & ConvertSQLDataType("nvarchar", BillingInformation) & "', "
strSQL=strSQL & "@Creator='" & ConvertSQLDataType("nvarchar", Creator) & "', "
strSQL=strSQL & "@CreationTime=" & ConvertSQLDataType("datetime", CreationTime) & ", "
strSQL=strSQL & "@LastModifier='" & ConvertSQLDataType("nvarchar", LastModifier) & "', "
strSQL=strSQL & "@LastModificationTime=" & ConvertSQLDataType("datetime", LastModificationTime) & ", "
strSQL=strSQL & "@Body='" & ConvertSQLDataType("ntext", Body) & "'"

Conn.Execute strSQL
If Err.Number<>0 Then
DebugError Err.Number & ":" & Err.Description & "-" & strSQL
End If

Conn.Close

set rec = nothing
set conn = nothing
If Err.Number<>0 Then DebugError "SaveRequest Error:" & Err.Number & ":" & Err.Description
End Function

Function DeleteRequest(EntryID)
On Error Resume Next
Dim Conn,Rec,strSQL
Set Conn = CreateObject("ADODB.Connection")
Set Rec = CreateObject("ADODB.Record")

Conn.ConnectionString = connectionString
Conn.Open

strSQL="Exec DeleteRequest "
strSQL=strSQL & "@EntryID='" & ConvertSQLDataType("nvarchar", EntryID) & "'"

Conn.Execute strSQL

Conn.Close

set rec = nothing
set conn = nothing
If Err.Number<>0 Then DebugError "DeleteRequest Error:" & Err.Number & ":" & Err.Description
End Function

'Exchange specific functions
Function GetEntryID(bstrURL)
'Function to get the Exchange EntryID from the URL to the item

On Error Resume Next

Set Conn = CreateObject("ADODB.Connection")
Set Rec = CreateObject("ADODB.Record")

Conn.Provider = "ExOLEDB.DataSource"
Conn.Open providerURL
Rec.Open bstrURL

byteEntryID = Rec.Fields.Item("http://schemas.microsoft.com/mapi/proptag/x0FFF0102")
GetEntryID = OctetToHexStr(byteEntryID)

Rec.Close
Conn.Close

set rec = nothing
set conn = nothing
End Function

'SQL specific functions
Function ConvertSQLDataType(DateType,Value)
'Function to convert VB Script values to SQL values
Select Case DateType
Case "int"
If (IsNull(Value) Or Value="" Or IsEmpty(Value)) Then
ConvertSQLDataType="NULL"
Else
ConvertSQLDataType=Value
End If
Case "datetime"
If (IsNull(Value) Or Value="" Or IsEmpty(Value)) Then
ConvertSQLDataType="NULL"
Else
ConvertSQLDataType="'" & FormatDateTime(Value,1) & " " & FormatDateTime(Value,3) & "'"
End If
Case "varchar", "nvarchar", "text", "ntext"
ConvertSQLDataType=Replace(Value,"'","''")
Case Else
ConvertSQLDataType=Value
End Select
End Function

'General functions
Function OctetToHexStr(arrbytOctet)
' Function to convert OctetString (byte array) to Hex string.
Dim k
OctetToHexStr = ""
For k = 1 To Lenb(arrbytOctet)
OctetToHexStr = OctetToHexStr & Right("0" & Hex(Ascb(Midb(arrbytOctet, k, 1))), 2)
Next
End Function

Sub DebugVariables()
WScript.Echo "URLName :" & URLName
WScript.Echo "StoreEntryID :" & StoreEntryID
WScript.Echo "EntryID :" & EntryID
WScript.Echo "LoggedBy :" & LoggedBy
WScript.Echo "LoggedFor :" & LoggedFor
WScript.Echo "Contacts :" & Contacts
WScript.Echo "Company :" & Company
WScript.Echo "Subject :" & Subject
WScript.Echo "Priority :" & Priority
WScript.Echo "PurchaseOrderNumber :" & PurchaseOrderNumber
WScript.Echo "RequestID :" & RequestID
WScript.Echo "Categories :" & Categories
WScript.Echo "DueDate :" & DueDate
WScript.Echo "StartDate :" & StartDate
WScript.Echo "CompletedDate :" & CompletedDate
WScript.Echo "Status :" & Status
WScript.Echo "Owner :" & Owner
WScript.Echo "Employees :" & Employees
WScript.Echo "TotalWork :" & TotalWork
WScript.Echo "ActualWork :" & ActualWork
WScript.Echo "BillingInformation :" & BillingInformation
WScript.Echo "Creator :" & Creator
WScript.Echo "CreationTime :" & CreationTime
WScript.Echo "LastModifier :" & LastModifier
WScript.Echo "LastModificationTime:" & LastModificationTime
WScript.Echo "Body :" & Body

WScript.Echo Action
WScript.Sleep 10000
End Sub

Sub DebugScript()
Set fso = CreateObject("Scripting.FileSystemObject")
set wfile = fso.opentextfile("D:\DataApps\Exchange\Logs\Request" & Year(Now()) & Right("0" & Month(Now()),2) & Right("0" & Day(Now()),2) & ".txt",8,true)
wfile.write vbNewLine & Now() & "," & Action & "," & itemURL & "," & EntryID
wfile.close
set fso = nothing
set wfile = nothing
End Sub

Sub DebugError(strMessage)
Set fso = CreateObject("Scripting.FileSystemObject")
set wfile = fso.opentextfile("D:\DataApps\Exchange\Logs\Error.txt",8,true)
wfile.write vbNewLine & Now() & "," & Action & "," & itemURL & "," & strMessage
wfile.close
set fso = nothing
set wfile = nothing
End Sub


So we have our SQL and we have our main VBScript, so all that was left was to create the VBScript for the event sinks, which was no different to the Time event sinks other than a reference to the folder.

Conclusion tonight.... I have both folders syncing to my SQL server, woooooohoooooo!

I wont kick off the import of 24,000 items tonight, wouldn't want it impacting tomorrows work, so will kick this off at the weekend.

I'm sooooo glad I got the boring bit of replicating the code out of the way tonight!

Next step???? Well I think it has to be syncronizing the other way (only because it's going to the next interesting bit). As far as I can tell at the point I need to:
1) Get SQL syncronizing to the existing exchange folders, could be interesting to do this via SQL triggers??
2) Get a basic front-end for the SQL data going and test parallel working with the data
3) Do some linking to private Calendars and Tasks to enable usage of Outlook at some level
4) Tart up the front end to the SQL
5) Decomission Exchange Public Folders

Shouldn't take me long :-(

Wednesday, 21 March 2007

SQL Work

It's been a little while since the last post, no excuses, just been busy with other things.

The next step from the last post was to get some SQL work done so that I could pass the changes from the Exchange Event Sink through to SQL.

So I created a DB in SQL 2000 then created the table for the Time items I was going to be persisting. The following SQL script creates the basic table in which the Time items will sit.

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[Time]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[Time]
GO

CREATE TABLE [dbo].[Time] (
[GUID] uniqueidentifier ROWGUIDCOL NOT NULL ,
[ID] [int] IDENTITY (1, 1) NOT NULL ,
[URLName] [nvarchar] (256) COLLATE Latin1_General_CI_AS NOT NULL ,
[StoreEntryID] [nvarchar] (160) COLLATE Latin1_General_CI_AS NOT NULL ,
[EntryID] [nvarchar] (160) COLLATE Latin1_General_CI_AS NOT NULL ,
[ProjectTitle] [nvarchar] (256) COLLATE Latin1_General_CI_AS NULL ,
[Subject] [nvarchar] (256) COLLATE Latin1_General_CI_AS NOT NULL ,
[Contacts] [nvarchar] (128) COLLATE Latin1_General_CI_AS NULL ,
[Company] [nvarchar] (128) COLLATE Latin1_General_CI_AS NULL ,
[Employees] [nvarchar] (256) COLLATE Latin1_General_CI_AS NULL ,
[Start] [datetime] NULL ,
[End] [datetime] NULL ,
[Duration] [int] NULL ,
[RequestID] [nvarchar] (16) COLLATE Latin1_General_CI_AS NULL ,
[BillingCategory] [nvarchar] (32) COLLATE Latin1_General_CI_AS NULL ,
[BillingDuration] [int] NULL ,
[Type] [nvarchar] (32) COLLATE Latin1_General_CI_AS NULL ,
[Categories] [nvarchar] (128) COLLATE Latin1_General_CI_AS NULL ,
[Creator] [nvarchar] (32) COLLATE Latin1_General_CI_AS NULL ,
[CreationTime] [datetime] NULL ,
[LastModifier] [nvarchar] (32) COLLATE Latin1_General_CI_AS NULL ,
[LastModifcationTime] [datetime] NULL ,
[Body] [ntext] COLLATE Latin1_General_CI_AS NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

ALTER TABLE [dbo].[Time] WITH NOCHECK ADD
CONSTRAINT [PK_Time] PRIMARY KEY CLUSTERED
(
[ID]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Time] ADD
CONSTRAINT [DF_Time_ID] DEFAULT (newid()) FOR [GUID]
GO

Theres not much special about the above table, it just replicates the fields from the Exchange Public Folder that I reckon I will need in the eventual solution. I suppose the only thing new for me is the use of UniqueIdentifier. I thought I'd better plan this in for replication purposes, how I'm going to use it is a matter I've not thought about yet!

The next thing for me to do was to create a Stored Procedure to update this table. I wanted a simple procedure that I could use to either create a new item or, given an ID, update an item. The following Stored Procedure is what I've come up with:

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[SaveTime]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[SaveTime]
GO

SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS OFF
GO


CREATE PROCEDURE SaveTime
(
@GUID uniqueidentifier=NULL,
@ID int=0,
@URLName nvarchar(256)='',
@StoreEntryID nvarchar (160),
@EntryID nvarchar (160),
@ProjectTitle nvarchar (256)=NULL,
@Subject nvarchar (256),
@Contacts nvarchar (128)=NULL,
@Company nvarchar (128)=NULL,
@Employees nvarchar (256)=NULL,
@Start datetime=NULL,
@End datetime=NULL,
@Duration int=NULL,
@RequestID nvarchar (16)=NULL,
@BillingCategory nvarchar (32)=NULL,
@BillingDuration int=NULL,
@Type nvarchar (32)=NULL,
@Categories nvarchar (128)=NULL,
@Creator nvarchar (32)=NULL,
@CreationTime datetime=NULL,
@LastModifier nvarchar (32)=NULL,
@LastModifcationTime datetime=NULL,
@Body ntext=NULL
)
AS

SET NOCOUNT ON

DECLARE
@trncnt int,
@ErrorNumber int

SELECT @ErrorNumber = -1

SELECT @trncnt = @@trancount

IF @trncnt = 0
BEGIN TRANSACTION T1
ELSE
SAVE TRANSACTION T1

IF @ID IS NULL
SET @ID = 0

IF @ID=0 --No ID passed so INSERT
BEGIN

SET @GUID=NEWID()

INSERT INTO Time
(GUID, URLName, StoreEntryID, EntryID, ProjectTitle, Subject, Contacts, Company, Employees, Start, [End], Duration, RequestID, BillingCategory, BillingDuration, Type, Categories, Creator, CreationTime, LastModifier, LastModifcationTime, Body)
VALUES
(@GUID, @URLName, @StoreEntryID, @EntryID, @ProjectTitle, @Subject, @Contacts, @Company, @Employees, @Start, @End, @Duration, @RequestID, @BillingCategory, @BillingDuration, @Type, @Categories, @Creator, @CreationTime, @LastModifier, @LastModifcationTime, @Body)
SET @ID=@@IDENTITY

END
ELSE --ID Passed so UPDATE
BEGIN
UPDATE Time
SET
URLName=@URLName,
StoreEntryID=@StoreEntryID,
EntryID=@EntryID,
ProjectTitle=@ProjectTitle,
Subject=@Subject,
Contacts=@Contacts,
Company=@Company,
Employees=@Employees,
Start=@Start,
[End]=@End,
Duration=@Duration,
RequestID=@RequestID,
BillingCategory=@BillingCategory,
BillingDuration=@BillingDuration,
Type=@Type,
Categories=@Categories,
Creator=@Creator,
CreationTime=@CreationTime,
LastModifier=@LastModifier,
LastModifcationTime=@LastModifcationTime,
Body=@Body
WHERE (ID=@ID)
END

SELECT @ID

IF @@Error <> 0 GOTO ErrorHandler

IF @trncnt = 0
COMMIT TRANSACTION

RETURN (0)

ErrorHandler:
ROLLBACK TRANSACTION
RETURN (100)

GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO


Not the biggest or most comprenhsive of posts, but it's a move forward, so that's good. The next step I have to do is write the VB Script which calls the Stored Procedure when an item changes.

But considering I'm off to Murcia in Spain on Saturday, then it's going to be at least a couple of weeks until I revisit this.