给定SQL Server中的一个表,该表保存来自三个源表的合并数据,包括一个名为OFFICE的列,用于区分记录。
三个源表保存来自三个办事处的数据。
我想动态创建一个Excel文件,根据三个不同的不同办公室(例如office1,office2,office3),在一个工作簿中有3个工作表,导致每个工作表根据其办公室包含相关数据。
请推荐在SSIS中使用动态Excel目标的方法,因为我不想使用创建模板文件的方法,然后将该模板复制到目标excel文件。
答案 0 :(得分:2)
虽然这可以使用scipt任务和C#来完成,但是可以使用更简单的解决方案 http://www.rafael-salas.com/2006/12/import-header-line-tables-_116683388696570741.html
和后续行动
http://www.rafael-salas.com/2008/03/ssis-and-dynamic-excel-destinations_01.html#!
但是要总结相关细节,您需要使用“执行SQL任务”在运行时动态创建工作表,然后再将其用作目标。
创建一个新变量来保存工作表名称,并在迭代它们时将此变量设置为您正在使用的Office。
此外,创建一个变量来保存将创建每个工作表的Create table语句。 例如,
“CREATE TABLE "+ @[User::SheetName] + "
(HeaderID
INTEGER,HeaderName
NVARCHAR(50),LineID
INTEGER,LineName
NVARCHAR(50),{{1} } NVARCHAR(50))“
并将For Each容器内的Execute SQL任务的SQLSourceType属性设置为Variable,并选择您创建的变量以保存create语句。
在Excel目标组件中,将数据访问模式更改为“表名称或视图名称变量”,然后从变量下拉列表中选择您创建的工作表名称变量。
答案 1 :(得分:0)
我有几个执行类似功能的SSIS包。单个Excel文件由多个工作表组成,每个工作表由单独的SQL查询的结果填充。以下是我应用的基本通用步骤。在开始之前,请确保为要应用的数据库和输出Excel文件创建连接管理器。
1)在Control flow中创建一个Script任务,并按如下方式填充它。在这里,我将创建Excel文件以及它将包含的工作表。 (工作表不应包含任何空格或特殊字符。)下面的代码在C#中。
using System;
using System.IO;
using System.Collections.Generic;
using System.Data;
using System.Text;
using Excel = Microsoft.Office.Interop.Excel;
using Microsoft.SqlServer.Dts.Runtime;
namespace ST_87e8d62a054b4e16b60297154afc19d8.csproj
{
[System.AddIn.AddIn("ScriptMain", Version = "1.0", Publisher = "", Description = "")]
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
{
#region VSTA generated code
enum ScriptResults
{
Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
};
#endregion
public void Main()
{
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;
object misValue = System.Reflection.Missing.Value;
xlApp = new Excel.ApplicationClass();
xlWorkBook = xlApp.Workbooks.Add(misValue);
//Create First worksheet
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
xlWorkSheet.Name = "Names";
//Define column headers for "RawData" WorkSheet
xlWorkSheet.Cells[1, 1] = "First Name";
xlWorkSheet.Cells[1, 2] = "Last Name";
xlWorkSheet.Cells[1, 3] = "Title";
// Create Second Worksheet
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(2);
xlWorkSheet.Name = "Addresses";
//Define column headers for "CCDN" WorkSheet
xlWorkSheet.Cells[1, 1] = "Street";
xlWorkSheet.Cells[1, 2] = "City";
xlWorkSheet.Cells[1, 3] = "State";
xlWorkSheet.Cells[1, 4] = "Zip";
xlWorkSheet.Cells[1, 5] = "Country";
string Filename = "C:\\MyFile.xls";
if (File.Exists(Filename))
{
File.Delete(Filename);
}
xlWorkBook.SaveAs(Filename, Excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, Excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue);
xlWorkBook.Close(true, misValue, misValue);
xlApp.Quit();
releaseObject(xlWorkSheet);
releaseObject(xlWorkBook);
releaseObject(xlApp);
Dts.TaskResult = (int)ScriptResults.Success;
}
2)在数据库中创建两个临时填充的表。也就是说,将为第一个工作表的结果填充一个表,并为第二个工作表的结果填充第二个表。这是一个很好的命名方法,用“Working_”为每个表的名称作序,以便您了解每个表的用途。我采用使用表而不是视图的方法是因为我喜欢对我的结果进行排序(ORDER BY),这不能用视图完成。
3)在控制流下添加两个执行SQL任务到SSIS包。第一个任务将运行INSERT SQL语句,该语句将填充您刚刚创建的第一个表,第二个任务将运行另一个INSERT SQL语句,该语句将填充刚刚创建的第二个表。
4)在控制流下添加两个数据流任务的SSIS包。第一个用于填充第一个工作表,第二个用于填充第二个工作表。
5)选择第一个数据流任务并在数据流下添加一个OLE DB源,您将在其中定义OLE DB连接管理器(您的数据库),然后是表或视图。选择创建的第一个新表。确保选择了所有感兴趣的列,并且可以执行预览。
6)添加数据转换流程任务,然后添加Excel目标流程任务。
7)对第二个工作表和表格重复步骤5和6。
8)最后在Control Flow下添加一个Excel SQL Task,它将删除两个Working Table的内容。您不希望下次运行包时包含旧内容。
现在,如果您想在Excel文件完成后对其进行格式化并给您的经理留下深刻印象,您也可以在代码中使用最终的任务脚本(也使用C#)。关于这种方法的好处是你不必在SQL中应用任何特殊的格式化函数,Excel正在完成所有工作。实际上,您可以在步骤1中包含格式,并在以下步骤中复制数据后,它会自动格式化。与任何报表输出一样,如果让Excel或SSRS更有效地执行他们最擅长的操作,那么使SQL执行格式化步骤(向数据库服务器添加其他工作)没有意义。
public void Main()
{
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;
object misValue = System.Reflection.Missing.Value;
Excel.Range xlRange;
xlApp = new Excel.ApplicationClass();
string Filename = "C:\\MyFile.xls";
xlWorkBook = xlApp.Workbooks.Open(FileName, 0, false, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
//Format cells in Names worksheet
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
//Set the header range in bold font
xlRange = xlWorkSheet.get_Range("a1", "p1");
xlRange.Font.Bold = true;
xlRange.WrapText = true;
//Freeze first row listing headers
xlWorkSheet.Application.ActiveWindow.SplitRow = 1;
xlWorkSheet.Application.ActiveWindow.FreezePanes = true;
//Auto adjust the width of each column
xlWorkSheet.Columns.AutoFit();
xlRange = xlWorkSheet.get_Range("c1", "j6467");
xlRange.Cells.Locked = false;
xlRange.Interior.Color = 65535;
xlRange = xlWorkSheet.get_Range("o1", "p6467");
xlRange.Cells.Locked = false;
xlRange.Interior.Color = 65535;
//Do not alert when saving changes to Excel file.
xlWorkBook.Application.DisplayAlerts = false;
//Save Excel file modifications
xlWorkBook.Save();
//Close workbook and application
xlWorkBook.Close(true, misValue, misValue);
xlApp.Quit();
//Release from cache.
releaseObject(xlWorkSheet);
releaseObject(xlWorkBook);
releaseObject(xlApp);
//Set formatting of percent cells
xlRange = xlWorkSheet.get_Range("d3", "d7");
xlRange.NumberFormat = "###,###%";
//Define the top left cell and bottom right cell of the table in the Excel worksheet
xlRange = xlWorkSheet.get_Range("c1", "c7");
//Draw grid of thin line around each cell in table
xlRange.BorderAround(Excel.XlLineStyle.xlContinuous, Excel.XlBorderWeight.xlThin, Excel.XlColorIndex.xlColorIndexAutomatic, 1);
//Draw thick border around entire table
xlRange = xlWorkSheet.get_Range("a1", "d7");
xlRange.BorderAround(Excel.XlLineStyle.xlContinuous, Excel.XlBorderWeight.xlThick, Excel.XlColorIndex.xlColorIndexAutomatic, 1);
//Right justify columns B and C
xlRange = xlWorkSheet.get_Range("b3", "c7");
xlRange.HorizontalAlignment = Excel.XlHAlign.xlHAlignRight;
//Do not alert when saving changes to Excel file.
xlWorkBook.Application.DisplayAlerts = false;
//Save Excel file modifications
xlWorkBook.Save();
//Close workbook and application
xlWorkBook.Close(true, misValue, misValue);
xlApp.Quit();
//Release from cache.
releaseObject(xlWorkSheet);
releaseObject(xlWorkBook);
releaseObject(xlApp);
Dts.TaskResult = (int)ScriptResults.Success;
}
就是这样。请注意,仅为了本示例的目的,我正在对文件名进行硬编码。但在我的实际代码中,我正在应用一个User变量,然后由另一个SQL语句填充从另一个数据库表中提取名称。对于最佳实践,最好将SSIS包完全由表驱动。这样,对名称和位置所做的任何更改都是在特定于SSIS包的记录中的数据库表中进行的...从而无需更新您的SSIS包并再次通过开发人员进行QA到生产生命周期。
希望这有帮助,如果您有任何问题,请告诉我。