将多工作表excel导入sql server并导出回多工作表excel

时间:2014-05-27 19:32:35

标签: sql-server excel powershell

我有一个多表excel工作簿,每个工作表中的列数未知。我循环遍历每个工作表并将数据导入到SQL Server中的表中。然后,我正在对该表运行查询以引入更多字段。然后,我希望将该查询的结果导出到多工作表excel工作簿中。我正在努力将其导出到多表工作簿中。在下面的代码中,我将它导出到csv,但我不确定这是最好的方法。我的计划是循环通过csvs来创建xlsx,但我可以看到导致问题,除非我将所有内容分成他们自己的目录,因为这会运行很多次。

Param(
 [String]$excelPath,
 [String]$serverName,
 [String]$databaseName,
 [String]$tableName,
 [String]$csvPath
 )

$ErrorActionPreference = 'Stop'

[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO.SqlDataType') | Out-Null

Trap {
  $err = $_.Exception
  while ( $err.InnerException )
    {
    $err = $err.InnerException
    Write-Output $err.Message
    };
    exit 1
  }

if (test-path $excelTMGPath ) { rm $excelTMGPath } #delete the file if it already exists 

$excel = New-Object -ComObject excel.application 
$excel.visible = $False 
$excel.displayalerts=$False 
$workbook = $excel.Workbooks.Open($ExcelPath) 
    foreach ($ws in $workbook.Worksheets)
    {
    $workSheet = $ws.Name
    Write-Output "Working on worksheet $workSheet"
    $query = "select * from [$workSheet`$]";

    $connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=`"$excelPath`";Extended Properties=`"Excel 12.0 Xml;HDR=YES;IMEX=1`";"

    # Instantiate some objects which will be needed
    $serverSMO = New-Object Microsoft.SqlServer.Management.Smo.Server($serverName)
    $db = $serverSMO.Databases[$databaseName];

    $newTable = New-Object Microsoft.SqlServer.Management.Smo.Table ;
    $newTable.Parent = $db;
    $newTable.Name = $tableName ;

    $conn = New-Object System.Data.OleDb.OleDbConnection($connectionString)
    $conn.open()

    $cmd = New-Object System.Data.OleDb.OleDbCommand($query,$conn) 
    $dataAdapter = New-Object System.Data.OleDb.OleDbDataAdapter($cmd) 
    $dataTable = New-Object System.Data.DataTable 

    $dataAdapter.fill($dataTable)
    $conn.close()

    # Drop the table if it exists
    if($db.Tables.Contains($tableName).Equals($true))
    {
        ($db.Tables[$tableName]).Drop()
    }

    # Iterate the columns in the DataTable object and add dynamically named columns to the SqlServer Table object.
    foreach($col in $dataTable.Columns)
        {
        $sqlDataType = [Microsoft.SqlServer.Management.Smo.SqlDataType]::Varchar
        $dataType = New-Object Microsoft.SqlServer.Management.Smo.DataType($sqlDataType);
        $dataType.MaximumLength = 1000;
        $newColumn = New-Object Microsoft.SqlServer.Management.Smo.Column($newTable,$col.ColumnName,$dataType);
        $newColumn.DataType = $dataType;
        $newTable.Columns.Add($newColumn);
    }
    $newTable.Create();

    #bcp data into new table
    $connectionString = "Data Source=$serverName;Integrated Security=true;Initial Catalog=$databaseName;"
    $bc = New-Object ("Data.SqlClient.SqlBulkCopy") $connectionString
    $bc.DestinationTableName = "$tableName"
    $bc.WriteToServer($dataTable)


    #Make sure column 3 is named MasterAccountKey for joining purposes  
    $sqlColumnRename = 
@"
    USE $databaseName
    declare @MasterAccountKey varchar(255), @cmd varchar(500)
    set @MasterAccountKey = (select COLUMN_NAME from INFORMATION_SCHEMA.columns
    where table_name = 'zzzExcelSheet'
    and ordinal_position = 3);

    set @cmd = ('sp_RENAME ''zzzExcelSheet.' + @MasterAccountKey + ''', ''MasterAccountKey'', ''COLUMN''')

    exec (@cmd)
"@
    $SqlConnection = New-Object System.Data.SqlClient.SqlConnection
    $SqlConnection.ConnectionString = "Data Source=$serverName;Initial Catalog=$databaseName;Integrated Security = True"
    $SqlCmd = New-Object System.Data.SqlClient.SqlCommand
    $SqlCmd.CommandText = $sqlColumnRename
    $SqlCmd.Connection = $SqlConnection
    $SqlConnection.Open()
    $sqlCmd.ExecuteNonQuery()
    $SqlConnection.Close()

    # Connect to SQL and query data, extract data to SQL Adapter
    $SqlQuery = @"
    select t.*,
    b.Social_Security_Number as SSN,
    b.PRIMARY_NAME, 
    b.ADDR_LINE_1,
    b.ADDR_LINE_2,
    b.CITY,
    b.STATE,
    b.ZIP_CODE,
    from 
    other tables b
"@
    $SqlConnection = New-Object System.Data.SqlClient.SqlConnection
    $SqlConnection.ConnectionString = "Data Source=$serverName;Initial Catalog=$databaseName;Integrated Security = True"
    $SqlCmd = New-Object System.Data.SqlClient.SqlCommand
    $SqlCmd.CommandText = $SqlQuery
    $SqlCmd.Connection = $SqlConnection
    $SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
    Try{
    $SqlAdapter.SelectCommand = $SqlCmd
    }
    Catch
    {
    exit 1
    }
    $DataSet = New-Object System.Data.DataSet
    $nRecs = $SqlAdapter.Fill($DataSet)
    $nRecs | Out-Null
    #Populate Hash Table
    $objTable = $DataSet.Tables[0]
    #Export Hash Table to CSV File
    $objTable | Export-CSV $objTable | Export-CSV $csvPath -noType



    if (test-path $csvPath ) { rm $csvPath }


    }
$ws = $null
$workSheet = $null
$workbook.Close()
$workbook = $null
$excel.quit() 
while ([System.Runtime.InteropServices.Marshal]::FinalReleaseComObject($excel)) {}
$excel = $null

0 个答案:

没有答案