Import Excel Into SQL Server

Copied from here.
http://blogs.technet.com/b/sqlthoughts/archive/2008/10/03/out-sql-powershell-function-export-pipeline-to-a-new-sql-server-table.aspx
http://tools.perceptus.ca/text-wiz.php
http://dnhlmssql.blogspot.com/2013/05/from-excel-to-insert-into-another.html

##############################################################################
##
## out-sql.ps1
##
## by Alexey Yeltsov, Microsoft Corp.
## Raju Venkataraman Added some fixes for Table creation and Inserts
## Export pipeline contents into a new SQL table
##
## Parameters:
##    $SqlServer     - SQL Server
##    $Database      - Database name
##    $Table         - Table name
##    $DropExisting  - Drop $Table if it already exists and recreate it
##                    (default $false)
##    $RowId         - Add identity column named $RowId and make it a primary key.
##                    (default "RowID". Can pass $null if identity is not needed)
##
##
## Examples:
##
##    #First, load the function
##    . .\out-sql.ps1
##
##    #Export processes to table Process in database Scratch on local sql server
##    get-process | out-sql -SqlServer . -database Scratch -table Process -dropexisting $true
##
##    #Export volume details from 4 servers into a table
##    @("Server1","Server2","Server3","Server4") `
##    | % {$Server = $_ ; Get-WMIObject Win32_Volume -computer $Server } `
##    | Select-Object `
##        SystemName, `
##        Name, `
##        @{Name="CapacityGb";Expression={[math]::truncate($_.Capacity / 1Gb)}}, `
##        @{Name="FreeGb";Expression={[math]::truncate($_.FreeSpace / 1Gb)}} `
##    | out-sql -sqlserver . -database Scratch -table DiskVolume -dropexisting $true
##
##
##
##############################################################################

 $DebugPreference = "Continue"

function Out-Sql($SqlServer=$null,$Database=$null,$Table=$null,$DropExisting=$false,$RowId="RowID") {
  begin
  {
       $Line = 0
       [string]$CreateTable = ""
       if(-not $SqlServer) { throw 'Out-Sql expects $SqlServer parameter' }
       if(-not $Database) { throw 'Out-Sql expects $Database parameter' }
       if(-not $Table) { throw 'Out-Sql expects $Table parameter' }
       if($DropExisting) { write-debug "Note: If the table exists, it WILL be dropped and re-created."}

       $SqlConnectionString = "  Provider=sqloledb;" +
                           "  Data Source=$SqlServer;" +
                    "  Initial Catalog=$Database;" +
                    "  Integrated Security=SSPI;"

       write-debug "Will open connection to SQL server ""$SqlServer"" and will populate table ""$Table."""
       write-debug "Connection string: `n$SqlConnectionString"
       $SqlConnection = New-Object System.Data.OleDb.OleDbConnection $SqlConnectionString
       $SqlCommand = New-Object System.Data.OleDb.OleDbCommand "",$SqlConnection
       $SqlConnection.Open()
  }
  process
  {
       $Line ++

       $Properties = $_.PSObject.Properties
       if (-not $Properties)
       {
         throw "Out-Sql expects object to be passed on the pipeline. The object must have .PSObject.Properties collection."
       }

       #if we're at the first line, initialize the table
       if ($Line -eq 1)
       {
              #initialize SQL connection and create table

              if($DropExisting) { $CreateTable += "IF OBJECT_ID('$Table') IS NOT NULL DROP TABLE $Table;`n"}

              $CreateTable +="CREATE TABLE $Table ( `n"

              $col = 0
              if ($RowId)
              {
                     $col++;
                     $CreateTable +="$RowId INT NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED `n"
              }
              foreach($Property in $Properties)
              {
                     $col++;
                     if ($col -gt 1) { $CreateTable +="," }

                     # In below, why not use "if ($Property.Value -is [datetime])"?
                     # Because access can be denied to the value, but Property.TypeNameOfValue would still be accessible!
                     if ($Property.TypeNameOfValue -eq "System.DateTime")
                     {
                           $CreateTable +="["+"$($Property.Name)"+"]"+" DATETIME NULL `n"
                     }
                     else
                     {
                     $CreateTable +="["+"$($Property.Name)"+"]"+" NVARCHAR(MAX) NULL `n"

                     }
              }

              $CreateTable +=")"

              write-debug "Will execute SQL to create table: `n$CreateTable"

              $SqlCommand.CommandText = $CreateTable

              $rows = $SqlCommand.ExecuteNonQuery()

       }

       #Prepare SQL insert statement and execute it
       $InsertStatement = "INSERT $Table VALUES("
       $col = 0
       foreach($Property in $Properties)
       {
              $col++;
              if ($col -gt 1) { $InsertStatement += "," }

              #In the INSERT statement, do speacial tratment for Nulls, Dates and XML. Other special cases can be added as needed.
              if (-not $Property.Value)
              {
                     $InsertStatement += "null `n"
              }
              elseif ($Property.Value -is [datetime])
              {
                     $InsertStatement += "'" + $Property.Value.ToString("yyyy-MM-dd HH:mm:ss.fff") + "'`n"
              }
              elseif ($Property.Value -is [System.Xml.XmlNode] -or $Property.Value -is [System.Xml.XmlElement])
              {
                     $InsertStatement += "'" + ([string]$($Property.Value.Get_OuterXml())).Replace("'","''") + "'`n"
              }
              else
              {
                     $InsertStatement += "'" + ([string]$($Property.Value)).Replace("'","''") + "'`n"
              }
       }
       $InsertStatement +=")"

       write-debug "Running insert statement: `n $InsertStatement"

       $SqlCommand.CommandText = $InsertStatement
       $rows = $SqlCommand.ExecuteNonQuery()
  }
  end
  {
       write-debug "closing SQL connection..."
       $SqlConnection.Close()
  }
}



 function Import-Excel([string]$FilePath, [string]$SheetName = "")
{
    $csvFile = Join-Path $env:temp ("{0}.csv" -f (Get-Item -path $FilePath).BaseName)
    if (Test-Path -path $csvFile) { Remove-Item -path $csvFile }

    # convert Excel file to CSV file
    $xlCSVType = 6 # SEE: http://msdn.microsoft.com/en-us/library/bb241279.aspx
    $excelObject = New-Object -ComObject Excel.Application
    $excelObject.Visible = $false
    $workbookObject = $excelObject.Workbooks.Open($FilePath)
    SetActiveSheet $workbookObject $SheetName | Out-Null
    $workbookObject.SaveAs($csvFile,$xlCSVType)
    $workbookObject.Saved = $true
    $workbookObject.Close()

     # cleanup
    [System.Runtime.Interopservices.Marshal]::ReleaseComObject($workbookObject) |
        Out-Null
    $excelObject.Quit()
    [System.Runtime.Interopservices.Marshal]::ReleaseComObject($excelObject) |
        Out-Null
    [System.GC]::Collect()
    [System.GC]::WaitForPendingFinalizers()

    # now import and return the data
    Import-Csv -path $csvFile
}

function FindSheet([Object]$workbook, [string]$name)
{
    $sheetNumber = 0
    for ($i=1; $i -le $workbook.Sheets.Count; $i++) {
        if ($name -eq $workbook.Sheets.Item($i).Name) { $sheetNumber = $i; break }
    }
    return $sheetNumber
}

function SetActiveSheet([Object]$workbook, [string]$name)
{
    if (!$name) { return }
    $sheetNumber = FindSheet $workbook $name
    if ($sheetNumber -gt 0) { $workbook.Worksheets.Item($sheetNumber).Activate() }
    return ($sheetNumber -gt 0)
}

$ExcelSheetContent = Import-Excel -FilePath "C:\Dev\svn\database\Projects\NewMexico\DBSetup\Data\Excel.xlsx" -SheetName "Sheet1"
Write-Host $ExcelSheetContent

$ExcelSheetContent |Select-Object |out-sql -SqlServer "DEV\INS1" -Database "ETLSTage" -Table "TargetTable" -DropExisting "True"




You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *