I have an SSIS Data Flow that uses a script task to create a row, process the row, and then write the result of one of the columns to a variable in a destination script task.
Destination Script is simply:
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
'
Variables.CampaignId = Row.CampaignId
'
End Sub
DataFlow
Is there something I am missing here? Do I need to be calling the end of the component? or testing for the end of the rowset?
ReadWriteVariables need to be written to in PostExecute and cannot be written to in the RowBuffer.
Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Pipeline.Wrapper
Imports Microsoft.SqlServer.Dts.Runtime.Wrapper
<Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute> _
<CLSCompliant(False)> _
Public Class ScriptMain
Inherits UserComponent
Dim CampID As String
' This method is called after all the rows have passed through this component.
Public Overrides Sub PostExecute()
MyBase.PostExecute()
Variables.CampaignId = CampID
End Sub
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
CampID = Row.CampaignId
End Sub
End Class
Answered my own question, but hopefully this helps someone else whom the error code does not generate for them. After multiple runs I finally got an error code about readwrite variable outside of post execute which helped tremendously with troubleshooting. Gotta love Microsoft...
Related
I have a Powerpoint addin, which when I need to reference Globals.ThisAddin.Application (the current instance or active instance of powerpoint calling to the addin) It returns a null reference. I do need `Globals.ThisAddIn.Application' or another method to get the current active instance of Powerpoint because it is used to generate something in the active presentation's active slide.
Watches
I tried using watches to track the error, but it says the following.
Code
VBA
Private Sub tst()
Dim tmp As object
Set tmp = New object
tmp.dosomething ' error triggered is here
Set tmp = Nothing
End Sub
Simplified VB.NET
ThisAddin
Imports Microsoft.Office.Interop.PowerPoint
Imports System.Diagnostics
Public Class ThisAddIn
Private Sub ThisAddIn_Startup() Handles Me.Startup
End Sub
Private Sub ThisAddIn_Shutdown() Handles Me.Shutdown
End Sub
End Class
Custom Namespace and Class
Imports System.Data
Imports System.Diagnostics
Imports System.Runtime.InteropServices
Imports Ppt = Microsoft.Office.Interop.PowerPoint
Namespace CustomStuff
<ComVisible(True)> _
<InterfaceType(ComInterfaceType.InterfaceIsIDispatch)> _
Public Interface IObject
Sub DoSomething()
End Interface
<ComVisible(True)> _
<ClassInterface(ClassInterfaceType.None)> _
Public Class Obj
Implements IObject
<ComVisible(True)>
Public Sub DoSomething() Implements IObject.DoSomething
Dim cpres As Ppt.Presentation
cpres = Globals.ThisAddIn.Application.ActivePresentation ' <- error is here
With cpres.Slides(cpres.Windows(1).Selection.SlideRange.SlideIndex)
...
End With
End Sub
Private Sub New()
End Sub
<ComVisible(True)>
Protected Overrides Sub Finalize()
MyBase.Finalize()
End Sub
End Class
End Namespace
Software And IDE
The ThisAddIn class comes from a VSTO Add-in project. You can access this object by using the Globals.ThisAddIn property. But I don't see the code of add-in in your sample. It seems you are trying to use the Application property outside of boundaries of the add-in.
See Global access to objects in Office projects for more information.
There is possibly a few things wrong with the below. Haven't had a chance to test/debug the code yet as can't run it. It stating that no main method has been found. But there is? i've even changed it to shared etc. It's probably something obvious?
It's flagging - 'Sub Main' was not found in 'ConsoleApplication1.Module1' error.
Also the main method wasn't always a separate class, I was just trying stuff. I'm importing a reference - system.processes. Was initially created as a vb.form but realised i didn't want the form part and recreated as a console app (which is very possibly where the problem lies as it's one of the first console apps i've done).
Code is basically planned to act on a service dying. Report and try and manage the restart (not finished, ideas welcome).
Imports System
Imports System.Management
Imports System.ServiceProcess
Imports System.Diagnostics
Imports System.Threading
Imports System.IO
Module Module1
Public Class Control
Public Sub Main() 'Public Sub Main(ByVal sArgs() As String)
Dim restart As New Rest
restart.startTime = DateTime.Now()
restart.cr20Services()
restart.Report()
End Sub
End Class
Public Class Rest
public startTime As String
Dim logPath As String = "C:\cr20\restart.txt"
'Dim fileExists As Boolean = File.Exists(strFile)
Dim arrcr20ServicesInitialStatus As New ArrayList
Dim failedServices As New ArrayList
Dim arrcr20Services As New ArrayList
Public Sub cr20Services()
'cr20 Services
arrcr20Services.Add("cr20 service")
arrcr20Services.Add("cr20 router")
For Each cr20Service In arrcr20Services
arrcr20ServicesInitialStatus.Add(cr20Service & " - " & cr20Status(cr20Service))
cr20Restore(cr20Service)
Next
End Sub
Private Function cr20Status(ByVal cr20Service As String)
Dim service As ServiceController = New ServiceController(cr20Service)
Return service.Status.ToString
End Function
Private Sub cr20Restore(ByVal cr20Service As String)
Dim service As ServiceController = New ServiceController(cr20Service)
'Dim p() As System.Diagnostics.Process = System.Diagnostics.Process.GetProcessesByName("calc")
If (service.Status.Equals(ServiceControllerStatus.Stopped)) Or (service.Status.Equals(ServiceControllerStatus.StopPending)) Then
failedServices.Add(service)
service.Stop()
Thread.Sleep(10000) 'give service 10 seconds to stop
service.Start()
End If
End Sub
I want to run some processing-intensive code in a thread upon starting Excel, and have included a simplified example below. A call to clsInit.Main is the starting point. The code executed in this thread (Sub DoIt) then modifies a variable (rng) that will be saved for use later when I access it by calling Sub GetIt. It doesn't work. Why? Thanks for the help.
Imports System.Threading
Public Class clsInit
Shared Sub Main()
Dim t As New Thread(AddressOf clsTest.DoIt)
t.Start()
End Sub
End Class
Public Class clsTest
Private Shared rng As Excel.Range
Public Shared Sub DoIt()
rng = Globals.ThisAddin.Application.ActiveCell
End Sub
Public Shared Sub GetIt()
MsgBox(rng.Address)
End Sub
End Class
I'm trying to dump all input0Buffer to a txt file, to end my struggle with making the flat destination re-usable as i've over 100 package and each structure and columns are different.
I'm redirecting the error rows to a flat file, so it's a nightmare to set that manually in every package, so I wanna write the whole input without specifieng Row.Name, all of them into text file.
I'm up to the point that i'm getting only one column!! it's driving me crazy!!
Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Pipeline.Wrapper
Imports Microsoft.SqlServer.Dts.Runtime.Wrapper
Imports System.IO
Imports System.Reflection
Imports System.Xml
Imports Microsoft.SqlServer.Dts.Pipeline
<Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute()> _
<CLSCompliant(False)> _
Public Class ScriptMain
Inherits UserComponent
Dim textWriter As StreamWriter
Private inputBuffer As PipelineBuffer
Public Overrides Sub ProcessInput(ByVal InputID As Integer, ByVal Buffer As Microsoft.SqlServer.Dts.Pipeline.PipelineBuffer)
inputBuffer = Buffer
MyBase.ProcessInput(InputID, Buffer)
End Sub
Public Overrides Sub PreExecute()
MyBase.PreExecute()
textWriter = New StreamWriter( "c:\Test4.txt", True)
End Sub
Public Overrides Sub PostExecute()
MyBase.PostExecute()
textWriter.Close()
''
End Sub
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
Dim delim As String = ", "
Dim RowCount As Integer = 0
For RowCount = 0 To inputBuffer.ColumnCount = -1
If inputBuffer.Item(RowCount).ToString() = "" Then
inputBuffer.Item(RowCount) = String.Empty
End If
Next
textWriter.WriteLine(inputBuffer.Item(RowCount).ToString() & delim)
End Sub
End Class
can anyone help me please?
The issue is where your write is at. You are writing outside of your For loop. You loop through each row and set the value of the entry to String.Empty but you aren't doing any writing to the textWriter here. Adjust the code as follows:
Dim myBuilder As New StringBuilder
For RowCount = 0 To inputBuffer.ColumnCount = -1
If inputBuffer.Item(RowCount).ToString() = "" Then
inputBuffer.Item(RowCount) = String.Empty
End If
myBuilder.Append(inputBuffer.Item(RowCount).ToString() & delim)
Next
textWriter.WriteLine(myBuilder.ToString)
That will ensure that each column gets written. The only issue will be that your last column will have a delimiter after it. You might want to trim that off before you write it. Also, you will need to add an Imports System.Text to your code as well.
One note I wanted to add since it can cause some confusion: your loop counter is called RowCount when it is performing the act of counting columns (ColumnCount-1 shows us that). That might cause some confusion down the road and assumptions could be made that might cause coding mistakes.
This is with SQL 2005.
I have a script component inside a Data Flow Task. I would like to read from the input columns and write the data to a global user variable.
I've set my input columns and added my global user variable as a ReadWriteVariable to the script component properties.
Here is my code, I'm just trying to alter the value of the global user variable here, but its not working. When I write out the value of the variable in another task it still has its default value:
Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Runtime
Imports Microsoft.SqlServer.Dts.Pipeline.Wrapper
Imports Microsoft.SqlServer.Dts.Runtime.Wrapper
Public Class ScriptMain
Inherits UserComponent
Dim updateSQL As String
Public Sub Main()
Dim vars As IDTSVariables90
VariableDispenser.LockOneForWrite("SQL_ATTR_Update", vars)
vars("SQL_ATTR_Update").Value = "Test"
vars.Unlock()
End Sub
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
'updateSQL = Row.ITMID + Row.PRCCAT
End Sub
End Class
I have also tried with no luck:
Me.ReadWriteVariables("SQL_ATTR_Update").Value = "Test"
I figured it out.
From MS:
In Script component code, you use
typed accessor properties to access
certain package features such as
variables and connection managers.
The PreExecute method can access only
read-only variables. The PostExecute
method can access both read-only and
read/write variables.
For more information about these
methods, see Coding and Debugging the
Script Component.
http://msdn.microsoft.com/en-us/library/ms136031.aspx
It looks like Dts is only available in Script Task.
Here is what the code looks like:
Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Runtime
Imports Microsoft.SqlServer.Dts.Pipeline.Wrapper
Imports Microsoft.SqlServer.Dts.Runtime.Wrapper
Public Class ScriptMain
Inherits UserComponent
Dim updateSQL As String
Public Overrides Sub PostExecute()
Me.ReadWriteVariables("SQL_ATTR_Update").Value = "Test"
End Sub
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
'updateSQL = Row.ITMID + Row.PRCCAT
End Sub
End Class
Here is how you could do it:
http://microsoft-ssis.blogspot.com/2011/01/how-to-use-variables-in-script.html
Use
Dts.Variables("SQL_ATTR_Update").Value = "Test"
And SQL_ATTR_Update needs to be a global variable and listed in your ReadWriteVariables for that script task.