Tuesday, August 27, 2013

How to: Send Emails by Script Task in SSIS

Sending emails are common tasks in control flow of SSIS packages. We need to inform users when packages run completely or fail. Script Task in SSIS provides a more simple but more flexible approach than the 'Send Mail Task'. Using 'Script Task', we can customize our sending email tasks. That is to say, with 'Script Task', we can configure senders, recipients, subjects, and bodies of an e-mail message. OK, let's get started!


First, you need to add the following for the header of your script.


Imports Microsoft.SqlServer.Dts.Runtime
Imports System.Net.Mail
Imports System.Net


Then, define variables:


Dim myHtmlMessage As MailMessage
Dim mySmtpClient As SmtpClient

The sender, recipient, subject, and body of an e-mail message may be specified as parameters when a MailMessage is used to initialize a MailMessage object.

Below is the whole script body:


Imports System
Imports Microsoft.SqlServer.Dts.Runtime
Imports System.Net.Mail
Imports System.Net


Public Class ScriptMain
  Public Sub Main()
    Dim myHtmlMessage As MailMessage
    Dim mySmtpClient As SmtpClient


    myHtmlMessage =
    New MailMessage(sender, recipient, "Subject", "body1." + vbCrLf + vbCrLf + "body2:" + Dts.Variables("System::MachineName").Value.ToString + vbCrLf + "Execution by:" + Dts.Variables("System::UserName").Value.ToString + vbCrLf + "Package StartTime: " + Dts.Variables("System::StartTime").Value.ToString + vbCrLf + vbCrLf + strSuccessMessage)

   mySmtpClient =
    New SmtpClient(Dts.Variables("cvarSMTPServer").Value.ToString())
  mySmtpClient.Send(myHtmlMessage)

  Dts.TaskResult = Dts.Results.Success
  End Sub
End Class


Now you can send emails by executing the task!

More freebies to addon


If you would like to achieve even more, keep reading.

  1. Attachments 

    In order to add attachment to emails, you need use
        myHtmlMessage..Attachments.Add(New Attachment("c:\textfile1.txt"))

      

  2. Users and Password

    The credentials returned by DefaultNetworkCredentials represents the authentication credentials for the current security context in which the application is running. mySmtpClient.Credentials = CredentialCache.DefaultNetworkCredentials

    If you don't want to use windows authentication to connect to your SMTP host and want to specify a different username and password, you can then use NetworkCredential class as shown below

     mySmtpClient.Credentials = New NetworkCredential(UserName, Password, Domain)

Wednesday, August 14, 2013

Stairway to Integration Service: Script Task

Another effective way to make SSIS packages dynamic is to write custom code that perform tasks you cannot perform with the built-in components. Here is a cookbook/cheatsheet that will speed up your learning of customized script tasks or components.


There are two important features you need to determine before you click "Edit Scripts" button. First of all, you need to add existing variables to the ReadOnlyVariables and ReadWriteVariables lists in the Script Transformation Editor or Script Task Editor to make them available to the custom script. Secondly, you need to determine which languages you would like to use: C# or Visual Basic.
Besides these, you need to add necessary libraries at the beginning of scripts. You can refer the article of Adding the Script Task to Your SSIS Packages for detailed steps.

Note that the following examples are all for 2008 version. This is not an exhaustive list. Please stay tuned for more tasks accomplished by Script Task in SSIS:


ProblemsExpression
Get files' name from readable variables into String sfilePathname.Solution 1:
Dim sfilePathname As String
sfilePathname = Dts.Variables("vFilePathName").Value.ToString

Solution 2:
Dim sfilePathname As String = Dts.Variables("vFilePathName").Value
Get the date when the file was created.Dts.Variables("vFileDate").Value = File.GetLastWriteTime(sfilePathname)
Get dateStamp from filename if it contains date info at last 6 strings.Dim dateStamp As String = sfilePathname.Substring(sfilePathname.LastIndexOf(("_")) + 1, 6)
Output value of dateStamp to ReadWriteVariables vYrMon.Dts.Variables("vYrMon").Value = CInt(dateStamp)

Get substring of dateStamp.Dim sYear As String = dateStamp.Substring(0, 4)
Get the system information from system variables.strSystemErrorEmailFrom = Trim(Dts.Variables("System::MachineName").Value.ToString())
Send SMTP mails.// Add "Imports System.Net.Mail" at the top
Dim myHtmlMessage As MailMessag 
Dim mySmtpClient As SmtpClient

myHtmlMessage=New MailMessage(strSystemErrorEmailFrom, strSystemErrorEmailTo, "Subject", "body")
    mySmtpClient =  New SmtpClient( Dts.Variables("cvarSMTPServer").Value.ToString() )
    mySmtpClient.Credentials = CredentialCache.DefaultNetworkCredentials
    mySmtpClient.Send(myHtmlMessage)
    Dts.TaskResult = Dts.Results.Success
Convert text to proper case
(ex. 1st letter in each word is uppercase)
Row.OutputName = StrConv(Row.InputName, VBStrConv.ProperCase)
Build Event Handler for OnError Event.Public Sub Main()
        Dim arrErrorMessages As Collections.ArrayList
        Try
            arrErrorMessages = CType(Dts.Variables("objErrorMessages").Value, Collections.ArrayList)
        Catch ex As Exception
            arrErrorMessages = New Collections.ArrayList()
        End Try
        arrErrorMessages.Add("Error on Component:[" + Dts.Variables("SourceName").Value.ToString() + "]: " + Dts.Variables("ErrorDescription").Value.ToString())
        Dts.Variables("objErrorMessages").Value = arrErrorMessages
        Dts.TaskResult = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success
End Sub
Get the filename from a full file path.Solution 1:
Dim fileName As String = "C:\mydir\test.txt"

Dim result As String = Path.GetFileName(fileName)
Console.WriteLine("GetFileName('{0}') returns '{1}'", fileName, result)

Solution 2:
RIGHT( @[User::FileName], FINDSTRING( REVERSE( @[User::FileName] ), "\\", 1 ) - 1 )
//Results: GetFileName('C:\mydir\test.txt') returns 'test.txt'
Dynamically pre-truncate table.sSQLScript = "DELETE FROM " + sTableName + vbCrLf
+ " WHERE " + sPKName + " > 0"
Dts.Variables("SQLScript1").Value = sSQLScript
Determine a varible's value depending on a file name If strFileName.Contains("BROUGHT").ToString Then
        intFacilityId = "1"
Else
        intFacilityId = "0"
End If
Get the filename without extension from a full file path.Dts.Variables("vFileName").Value = Path.GetFileNameWithoutExtension(Dts.Variables("vFilePath").Value.ToString) 
Split strings that delimited by "|".Dim sAry As String() = col1.Split("|")
Check file exists or not.Solution 1:
Dim directory As DirectoryInfo = New DirectoryInfo("c:\")
Dim file As FileInfo() = directory.GetFiles("*.txt")
If file.Length > 0 Then
   Dts.Variables("User::FileExists").Value = True
Else
   Dts.Variables("User::FileExists").Value = False
End If
Solution 2:
If (System.IO.File.Exists("C:\mydir\test.txt")) Then
      Dts.TaskResult = ScriptResults.Success
    Else
      Dts.TaskResult = ScriptResults.Failure
End If

Friday, August 9, 2013

How to: Pad a Number with Leading Zeros

As mentioned in the previous post "What do NDC, NCPDP, NABP, NPI mean? ", sometimes a column requires a fixed length, such as NDC is a 11-digit number. If the source file does not provide a fixed-length number and the data is already loaded to your database, you need to message the column by padding it with leading zeros.

Here are two solutions by using SQL scripts or by using user-defined functions (UDFs).

  • Solution 1:
             UPDATE [tableName]
             SET NDC = RIGHT(REPLICATE('0', 11) + CONVERT(VARCHAR,NDC),11)

  • Solution 2:
    • Be careful that length of NULL string is NULL.
    • CREATE FUNCTION dbo.PadLeft
      (@str INT, @PadWidth INT, @PadChar CHAR(1))
      RETURNS VARCHAR(255)
      AS
      BEGIN
      RETURN RIGHT(REPLICATE(@PadChar, @PadWidth) + CONVERT(VARCHAR,@str),@PadWidth)
      END
      GO
    • After creating the function above, you can test it with "select dbo.PadLeft(12345, 11, '0') ". The result should be "00000012345".