I am building an SSIS package consisting of some dataflow tasks that contain script components. In one of these script components I'm trying to assign a value to a read/write variable in the post execute sub as follows:
Public Overrides Sub PostExecute()
Me.ReadWriteVariables("User::pEndDate").Value() = proEndDate
MyBase.PostExecute()
End Sub
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
...
Try
...
proEndDate = Row.EndDate
MessageBox.Show("Assigning the project end date from the row: " & proEndDate.ToString)
proEndDate has the correct value in it per the message box, but the variable is never being updated. Does anyone know why?
"The variable is never being updated". I take it this means when you look at the Variable's window while the package is running, the value never changes from its original.
This is correct and the value will never change but your code is also correct.
The Variables window shows the Design-time value of all of your variables. The Run-time values are accessible through the Debug window. In your Local's window, you will see the current value. I wrote a more detailed answer over here
Why doesn't the Script Task code assign any value to ReadWriteVariables?
Related
I'm trying to call a Sub from another Form, but I get:
Error 2465: Application defined error or object defined error
I already know that to call a procedure from another form I can use the syntax:
Form(Name).Procedure
But, in this case I want to refer to this form from a variable (Type Form).
Code from form Parametro_Cadastro:
Dim formCaller As Form
Set formCaller = Application.Forms("Cadastro_Aluno").Form
If (Not formCaller Is Nothing) Then
'
formCaller.SetDadosParametroCadastro Me.txtKey.Value, dadoAlterado
Set formCaller = Nothing
End If
Code from form Cadastro_Aluno:
Sub SetDadosParametroCadastro(ByVal KeyValue As String, ByVal DataValue As String)
'
'...
End Sub
The code in Parametro_Cadastro gives Error 2465 on the line:
formCaller.SetDadosParametroCadastro Me.txtKey.Value, dadoAlterado`
...even before the Sub SetDadosParametroCadastroin the form Cadastro_Alunos to be called.
In the Immediate Window, the variable formCaller is already signed as Form\Form_Cadastro_Alunos as expected.
What can I do in this case?
EDIT
The only way it worked was to assign the variable formCaller to Access.Forms(formName) and not through Application.Forms(formName) or simply Forms(formName), so the code now is like below:
Code from form Parametro_Cadastro:
Dim formCaller As Form
Set formCaller = Access.Forms("Cadastro_Aluno")
If (Not formCaller Is Nothing) Then
'
formCaller.SetDadosParametroCadastro Me.txtKey.Value, dadoAlterado
Set formCaller = Nothing
End If
When I check the variable formCaller in the Imediate Window, I also get (as before) Forms\Form_Cadastro_Alunos.
The interesting thing is this only change make the code work as expected. Maybe the Forms member to be called is from Access Object instead of Applications?
Although you can call a procedure from a form, it's generally avoided and is considered bad practice.
Any Sub or Function that need to be shared should be placed in a separate, shared module.
Some excellent advice from Stewart # Bytes.com:
Form code modules are essentially 'private' in scope. Functions and subroutines defined in them are normally unavailable outside of the form concerned - although it is actually possible to call the functions and subroutines defined as Public in scope within a form code module from outside of that module.
Use of the keyword Public is not just a matter of suddenly adding one as a change of style. It reflects that you wish the subroutine, function or variable to be available outside of the scope of the code module concerned...
The code modules which can be created or opened from the Modules tab are the usual locations of public subroutines and functions. Named modules provide a means of grouping tasks by logical function, and if used consistently can be an aid to maintainability.
I use many several named modules in my applications, separating custom linked table maintenance from username parsing, e-mail handling and so on. I also include a "General" module which contains general bespoke functions that I find useful and re-use across multiple databases (for example, to return the current financial year or the current quarter within it).
All subroutines and functions defined using the Public keyword in the publicly-accessible code modules are available outside of the module concerned, whereas those defined as Private cannot be used outside of the scope of the code module in which they reside.
"If you must..."
If, for some reason, you must call a public sub from a form, the syntax is:
Call Forms!FormName.SubName
Note that the sub being called must have the Public keyword specified.
More Information:
MSDN : Understanding Scope and Visibility
Bytes.com : How and where to use Private or Public sub or function?
I can successfully refer to the value in a text box in the subreport footer using [subreportName].[Report].[textBoxName]. However, I would like to refer to a text box in the detail section. Using the above just gives the last value it contained - I would like to refer to a specific one (by field, say).
Is this possible, or is there some workaround?
Update: This is what I have so far. fieldA is the name of the text box that I want to use to pick out the correct entry (the correct entry will have "keyString" in this text box), and fieldB contains the value I want to actually store.
In the OnFormat event in the subreport detail section:
Dim varToStore As Double
Private Sub Detail_Format(Cancel As Integer, FormatCount As Integer)
If Me![fieldA] = "keyString" Then
varToStore = Me![fieldB]
End If
End Sub
In a new Module:
Function getVariable(Name As String)
If Name = "varToStore" Then
getVariable = varToStore
Else
getVariable = -1
End If
End Function
In the Control Source of the text box in the main report:
=getVariable("varToStore")
I'm using the general function getVariable since there are a few variables from the detail section that I'm planning to store, so I thought it would be easier to just pass arguments to one function, rather than having a function for each.
If you look at a textbox in the detail section of a continuous form, it is really only one object, even if there are many rows on the screen.
If you change a property, you change all rows. If you read its value, you get the value of the current record.
With the detail section of a report, it's similar. You can't refer to the textbox of any row except the last after it has been printed.
But you can while it is being printed. The OnFormat property of the detail section is most probably the best event to use.
Something like
Private Sub Detailbereich_Format(Cancel As Integer, FormatCount As Integer)
If Me!Keyfield = 4711 Then
' do something specific with the textbox of this specific row
End If
End Sub
To create this sub, open the property sheet of the details section of the subreport.
On the Events tab, select Event procedure for the On Format event. Edit it ("..." button) and you're there.
You can assign the textbox value to a public variable to pass it to the main report. But depending on where/when in the main report you want to use it, it may be too late.
New answer for the Update.
I assume your code doesn't work?
That would be because getVariable("varToStore") is evaluated when the main report is opened, but varToStore is set later, when the subreport is formatted.
So you need a different approach. Don't try to fish your data from the subreport, get it with SQL when the main report is opened. Something like:
Report_Open()
Me.mainTextField.Value = DLookup("fieldB", "SubReportTable", "fieldA = 'keyString'")
mainTextField would be unbound then.
If "keyString" is actually constant, you could even use the DLookup as control source. But I guess it's a variable, so it's easier to construct the DLookup call in VBA.
I have a form (named DateForm) that contains a textbox (named txt_AsOfDate), which displays a date value.
I have a separate SUB which has the following code:
Sub Test()
Dim AsOfDate As String
AsOfDate = txt_AsOfDate.Text
MsgBox (AsOfDate)
End Sub
When running it, I get the following error:
Run-time error '424': Object required
What is going on? I tried loading the DateForm at the beginning of the SUB, and also tried assigning the value by further defining the object schema like below, but no luck. What am I doing wrong?
AsOfDate = DateForm.txt_AsOfDate.Value
Try replacing txt_AsOfDate.Text with Form_DateForm.txt_AsOfDate.Text. Referring to a control directly in code by its name only works in the form, whereas I'm guessing this code is in a separate module.
In order to catch things like this, add Option Explicit to the top of your code modules. This forces the compiler to notify you if there is a variable being used which wasn't first declared with Dim.
I have a form called Form1. In Form1, I have the following code -
Dim details As clsDetails
Set details = getDetials(1) ' This fails. It doesn't assign a value.
The getDetails function is declared in a separate module as follows-
Public Function getDetials(detailNumber As Integer) As clsDetails
Dim details As clsDetails
Select Case detailNumber
Case "1"
Debug.Print "Inside case1"
Set details = getDetail1()
Debug.Print details.comment ' This prints correctly.
End Select
Set getDetails = details
End Function
However, when I execute the above code, somehow, the details variable in Form1 doesn't get set, even though the getDetails function is called and prints the details correctly inside it. How to rectify this?
Do you have the Option Explicit keyword defined?
It looks like you might have a typo. Your function is called getDetials, but the variable you're setting the result to is getDetails, so the return value is not getting set.
I fixed the typo and everything works as expected on my end. Using the Option Explicit keyword will catch these types of errors.
I think this may be a case of not having Option Explicit On
Check you have Option Explicit at the top of your form (and in fact everywhere)
Your type mistake declaring the function getDetials but then setting an object called getDetails to the newly created class is actually creating a new object and the function return is not being set at all.
Insert Option Explicit and you will see that it won't compile!
When you have added Option Explicit everywhere got to Tools>Options>Editor tab and tick the box that says Require variable declaration - that will make sure it is added every time you add a new code file to your project.
Before I give myself some sort of stress related heart attack.
Would anyone know how to complete the seemingly simply task of setting the result set of one data flow task (the result will be either a 0 or 1) and assigning that value to a variable.
I've created the variable ok.
The result set comes from an XML file with multiple elements. The flag (0 or 1) is the result from one of those elements, so I also need to know how to get the result set to be just that flag.
If anyone could help I would really really appreciate it.
Update : I eventually read the result (0,1) back to SQL Server into a flag table. Then used a Execute SQL script to read it back from SQL Server and to a variable. Not sure if this is the best way to have done it but it seems to have done the trick.
You can use a Data Flow Script component to transfer a data flow column value to an SSIS variable. However, you must follow certain rules when working with the Data Flow Script component and SSIS variables.
SSIS doesn't allow you to assign values to SSIS variables in the script procedure that processes rows. But there are pre- and post-execute procedures where you can handle the assignment.
In your Script component, add the SSIS variable to the ReadWriteVariables property. Edit the script and declare a variable in the ScriptMain class. Use the PreExecute procedure to initialize the variable. Use the ProcessInputRow procedure to assign the input -buffer column value to the script variable. And, use the PostExecute task to assign the value from the script variable to the SSIS variable.
Here's an example VB script component. It has an SSIS variable (MyOutVariable) that will get the output of the script variable (MyVar). The MyVar variable gets it's value from the MyNumber column in the data flow.
Public Class ScriptMain
Inherits UserComponent
Dim MyVar As Integer
Public Overrides Sub PreExecute()
MyBase.PreExecute()
'initialize variable local to data flow
MyVar = 0
End Sub
Public Overrides Sub PostExecute()
MyBase.PostExecute()
' output variable value to SSIS variable
Me.Variables.MyOutVariable = MyVar
End Sub
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
' logic to get value
MyVar = Row.MyNumber
End Sub
End Class