我有一个多表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