Saturday, 12 August 2017

SSIS For Each Loop Container Task to Load Multiple Text Files Data to SQL Server Destination

SSIS ForEach Loop Container Task to Load Multiple Source Text Files Data to SQL Server Destination
ForEach Loop Container is used repeat the tasks in a Pacakge. For example load data from each file in a directory to the destination table.

Example :
Suppose if we want load the source data from multiple Text .txt files to SQL Server destination and also need to update the Source File name in one column of the destination table, this can be done using the SSIS Foreach Loop container as follows :

Source Files (.txt) :
The Source files which we want to load to the Destination



 Destination Table :
The Destination Table ( Emp_Temp1) into which the above source files need to load.



Step 1: Creating Variables :
First create the two variables "FileName", "FilePath" and assign the one of the Source File to the variable "FileName" and assign the Source Files folder path to the variable "FilePath" as shown below :



Step 2: Create the Connections for Source and Destination:



Tamatam_DB : It is the Connection the SQL Server Database
Input_Src_Txt : It is the Connection for the Source Text files. 

Step 3: Creating dynamic Connection String for Source:
For Input_Src_Txt connection we have to make the Connection String dynamic to pick each source file as follows :

Go to connection properties and define the "Connection String" in Expressions as follows :



Step 4: Design the Control Flow:
Excute SQL Task : 
In this task we Truncate the destination SQL Table by defining the SQL  Statement as "Truncate Table Emp_Temp1"



For Each Loop Container : 
Add the For Each Loop Container in the Control Flow and set the Properties as follows:
In Collection tab, choose the Folder and Files ( you can use wild cards based on your files naming ) value as below.



Next in the Variable Mappings tab assign the dynamic file name variable "FileName" to store the filename in each loop.


Step 5: Design the Data Flow :
Next design the Data Flow to send the data from Source to Destination as follows :

In the above Data Flow, we have to use the Data Conversion to convert the data from Source format to Destination.

Also we have to the Derived Column transformation to Define a Column to Capture the Source File name, using the Variables as follows :






Now map the Columns to the respective Columns in Destination.

Step 6 : Final Output :
Now all the Text Files data with Source Files name loaded to the destination as follows :










 Thanks, TAMATAM

Thursday, 23 March 2017

How to Send a Range from an Active Sheet in an Outlook Email Body from Active Workbook with VBA

VBA Macro to Send a Range from an Active Sheet in an Outlook Email Body from Active Workbook
Sub Mail_Selection_Range_Outlook_Body()
    Dim Rng As Range
    Dim OutlookApp As Object
    Dim NewMail As Object

    Set Rng = Nothing
    On Error Resume Next

    Set Rng = ActiveSheet.Range("MyRng")
'--You can also use a Fixed range if you want
    'Set Rng = Sheets("YourSheet").Range("A1:D12").SpecialCells(xlCellTypeVisible)
    On Error GoTo 0

    If Rng Is Nothing Then
        MsgBox "The Selection is not a Range or the Sheet is Protected" & _
               vbNewLine & "Please Correct and try again.", vbOKOnly
        Exit Sub
    End If

    With Application
        .EnableEvents = False
        .ScreenUpdating = False
    End With

    Set OutlookApp = CreateObject("Outlook.Application")
    Set NewMail = OutlookApp.CreateItem(olMailItem)
    'Set NewMail = OutlookApp.CreateItem(0)
    
 '--Inserting Signature in Email Body
 '--Change only 'YourSignature.htm' to the name of your Signature
    SigString = Environ("appdata") & "\Microsoft\Signatures\Tamatam.htm"

    If Dir(SigString) <> "" Then
        Signature = GetBoiler(SigString)
    Else
        Signature = ""
    End If

 '--Selecting your desired Email Account for Sending From
 '--If the account is not in your profile, Then you need to use SentOnBehalfOfName
        For I = 1 To OutlookApp.Session.Accounts.Count
            If OutlookApp.Session.Accounts.Item(I) = "MyEmailAccountAlias@Domain.Com" Then
             MsgBox OutlookApp.Session.Accounts.Item(I) & " : This is account number " & I
                Acn_No = I
                Exit For
            End If
        Next I

'--Defining the Email Body Message
        Strbody = "<H3><B>TEST MAIL via EXCEL MACRO</B></H3>" & _
                    "This is sample test mail by Macro<br>" & _
                    "Please donot repond to it<br>" & _
                    "<A href=""https://excelkingdom.blogspot.in/"">Excel Kingdom</A>"
              
    On Error Resume Next

'--Opening a New Email to Send
    With NewMail
        .TO= "YourEmail@Domain.com" '--Your Email Id here
        .CC = ""
        .BCC = ""
        .Subject = "Test Message" '--Your Email Subject here
       '.Body = "This Your Email Boday ; '--You can use below one as well
        .HTMLBody = Strbody & "<br>" & "<br>" & _
                    RangetoHTML(Rng) & "<br>" & "<br>" & _
                    "<B>Thank you</B>" & "<br>" & "<br>" & Signature
        .SentOnBehalfOfName = OutlookApp.Session.Accounts.Item(Acn_No) 
        '--You can use below one as well
        '.SentOnBehalfOfName = "MyEmailAccountAlias@Domain.Com"
        '.SendUsingAccount = OutlookApp.Session.Accounts.Item(Acn_No)
        .Display '--Use .Display to show you the Email before sending it.
        .Send
    End With
    
    On Error GoTo 0

    With Application
        .EnableEvents = True
        .ScreenUpdating = True
    End With

    Set OutMail = Nothing
    Set OutApp = Nothing
End Sub

-- This is will call to above Procedure to Copy the Range from Active sheet to a .htm file then to the Email Message Body

Function RangetoHTML(Rng As Range)
    Dim FSO As Object
    Dim TS As Object
    Dim TempFile As String
    Dim TempWB As Workbook

'--Creating a Temporary .htm file to Copy the Range from Active sheet.
    'TempFile = Environ$("temp") & "\" & Format(Now, "dd-mmm-yyyy") & ".htm"
     TempFile = Environ("UserProfile") & "\Desktop\Test\" & Format(Now, "dd-mmm-yyyy") 
                                                                                                 & ".htm"

 '--Copy the range and Paste the data to newly created Workbook
    'Rng.Select
    Rng.Copy
    Set TempWB = Workbooks.Add(xlWBATWorksheet)

'--Copy Pasting the Range from  Active Sheet to a Temp Workbook Sheet
    With TempWB.Sheets(1)
        .Cells(1).PasteSpecial Paste:=8 'Paste with same Column Widths
        .Cells(1).PasteSpecial xlPasteValues, , False, False
        .Cells(1).PasteSpecial xlPasteFormats, , False, False
        .Cells(1).Select
        Application.CutCopyMode = False
        On Error Resume Next
        .DrawingObjects.Visible = True
        .DrawingObjects.Delete
        On Error GoTo 0
    End With

'--Publish the Sheet to a htm file from Temp Workbook Sheet
    With TempWB.PublishObjects.Add( _
         SourceType:=xlSourceRange, _
         Filename:=TempFile, _
         Sheet:=TempWB.Sheets(1).Name, _
         Source:=TempWB.Sheets(1).UsedRange.Address, _
         HtmlType:=xlHtmlStatic)
        .Publish (True)
    End With

 '--Reading all data from the htm file into RangetoHTML variable
    Set FSO = CreateObject("Scripting.FileSystemObject")
    Set TS = FSO.GetFile(TempFile).OpenAsTextStream(1, -2)
    RangetoHTML = TS.readall
    TS.Close
    RangetoHTML = Replace(RangetoHTML, "align=center x:publishsource=", _
                          "align=left x:publishsource=")

'--Closing the TempWB
    TempWB.Close SaveChanges:=False

'--Delete the htm file we used in this Function
    Kill TempFile

    Set TS = Nothing
    Set FSO = Nothing
    Set TempWB = Nothing
End Function

-- This is will call to above Procedure to Copy the Signature to the Email Message Body
Function GetBoiler(ByVal SigFile As String) As String
    Dim FSO As Object
    Dim TS As Object
    Set FSO = CreateObject("Scripting.FileSystemObject")
    Set TS = FSO.GetFile(SigFile).OpenAsTextStream(1, -2)
    GetBoiler = TS.readall
    TS.Close

End Function

How to Send Active Sheet as an Outlook Email Attachment with VBA

VBA Macro to Send Active Sheet as an Outlook Email Attachment from Active Workbook
The following Macro will copy the Active sheet data from the This/Active Workbook to a New Workbook with single sheet and Save that with Active sheet name, then it will send via Outlook as an Email Attachment, from a specified Email Account/Alias to the defined Users.
Sub Email_ActiveSheet_WB()
    Dim OutlookApp As Object
    Dim NewMail As Object
    Dim ActShtName As String
    Dim FileFullPath As String
       
    With Application
        .ScreenUpdating = False
        .EnableEvents = False
    End With

'Copying the Active Sheet data
    ActiveSheet.Cells.Copy
    ActShtName = ActiveSheet.Name
  
  'Saving the Active sheet data  into a new workbook with Active Sheet name_Today date
    Workbooks.Add (xlWBATWorksheet)
    ActiveSheet.Paste
    Application.CutCopyMode = False
    ActiveSheet.Range("A1").Select
    ActiveSheet.Name = ActShtName

    Application.DisplayAlerts = False

    ActiveWorkbook.SaveAs Environ("UserProfile") & "\Desktop\Test\" & ActShtName & "_" &                                                                Format(Now, "dd-mmm-yyyy") & ".xlsx"

'Storing the Saved file(which we used for attachment later) path into a Variable
    FileFullPath = ActiveWorkbook.Path & "\" & ActiveWorkbook.Name

    ActiveWorkbook.Close True

    Application.DisplayAlerts = True
  
'Setting up the objects of Outlook Application and New Email 
    Set OutlookApp = CreateObject("Outlook.Application")
    Set NewMail = OutlookApp.CreateItem(olMailItem)
    'Set NewMail = OutlookApp.CreateItem(0)

'Inserting Signature in Email Boday ; Change only 'YourSignature.htm' to the name of your Signature
    SigString = Environ("appdata") & "\Microsoft\Signatures\Tamatam.htm"

    If Dir(SigString) <> "" Then
        Signature = GetBoiler(SigString)
    Else
        Signature = ""
    End If

'Selecting your desired Email Account for Sending From Account
'If the account is not in your profile, Then you need to use SentOnBehalfOfName

        For I = 1 To OutlookApp.Session.Accounts.Count
            If OutlookApp.Session.Accounts.Item(I) = "MyEmailAccountAlias@Domain.Com" Then
             '--MsgBox OutlookApp.Session.Accounts.Item(I) & " : This is account number " & I
                Acn_No = I
                Exit For
            End If
        Next I

'Defining the Email Body Message
        Strbody = "<H3><B>TEST MAIL via EXCEL MACRO</B></H3>" & _
                    "This is Sample Test Email by Macro<br>" & _
                    "Please donot repond to It<br>" & _
                    "<A href=""https://excelkingdom.blogspot.in/"">Excel Kingdom</A>"
              
    On Error Resume Next

'Opening a New Email to Send

    With NewMail
        .TO = "YourEmail@Domain.com" 'Your Email Id here
        .CC = ""
        .BCC = ""
        .Subject = "Test Message" 'Your Email Subject here
       '.Body = "This Your Email Boday ; '--You can use below one as well
        .HTMLBody = Strbody & "<br>" & "<br>" & "<B>Thank you</B>" & "<br>" & Signature
        .Attachments.Add FileFullPath '-- Full Path of the Attachment where it is saved.
        .SentOnBehalfOfName = OutlookApp.Session.Accounts.Item(Acn_No) 
          '--You can use below one as well
        '.SentOnBehalfOfName = "MyEmailAccountAlias@Domain.Com"
        '.SendUsingAccount = OutlookApp.Session.Accounts.Item(Acn_No)
        .Display '--Use .Display to show you the Email before sending it.
        .Send
    End With
    
    On Error GoTo ErrMsg:
    
' Since mail has been sent with the attachment.You can kill the Source file if not required    
    Kill FileFullPath
    
' Set nothing to the objects created.
    Set NewMail = Nothing
    Set OutlookApp = Nothing
    
' Now set the application properties back to true.
    With Application
        .ScreenUpdating = True
        .EnableEvents = True
    End With
    MsgBox "Activesheet as Email Attchment Sent Successfully", vbOKOnly, "Job Done"
    Exit Sub

ErrMsg:
        MsgBox Err.Description

End Sub

'The Function to Look and Get the Email Signature; Calls into above Macro
   Function GetBoiler(ByVal SigFile As String) As String
      Dim FSO As Object
      Dim TS As Object
      Set FSO = CreateObject("Scripting.FileSystemObject")
      Set TS = FSO.GetFile(SigFile).OpenAsTextStream(1, -2)
      GetBoiler = TS.readall
      TS.Close

   End Function
---------------------------------------------------------------------------------------------------------------------
Note : Please note that You have to define both the Sub Procedure and Function in the same Module, to call Signature into your Email body.
---------------------------------------------------------------------------------------------------------------------

Thanks,
TAMATAM
         [ BI Developer ]

Follow Me by Email

ExcelKingdom-Popular Posts

ExcelKingdom-Random Posts