I have a report which uses an expression to provide data for each particular page. I have been able to get the report to display the correct data, however the column that the expression is in, is not necessary and the rest of the table will not fit on the page. I need to get rid of the column but reference the expression somewhere else on the report. I have tried a few things, such as referencing the text box but get Scope errors.
I would like the expression to display where the green line is, and make the first column invisible.
Any ideas how I can reference the value of this textbox in the desired location?
Current state of report:
expression ="Load Number: " & Fields!TPLD_SYS_NO.Value & " | " & "Vehicle:" & Fields!TPLD_TPVH_REG.Value & " | " & Fields!TPLD_REF.Value
expression used to reference 1st expression =ReportItems!TPLD_SYS_NO1.Value
error The value expression for the textbox 'textbox8' refers to the report item 'TPLD_SYS_NO1'. Report item expressions can only refer to other report items in the same grouping scope or a containing grouping scope
This is from memory, zero testing I'm afraid so it might not be quite right but it should be close enough to follow.
A couple of options.
If the report will only ever show one value for this expression then you should be able to just use your original value expression directly in the 'new' text box but where you have Fields!myField.value, replace these with FIRST(Fields!myField.Value, "myDataset") where myDataset refers to the name of your dataset (you must include the quotes).
If the report is grouped so this expression will evaluate to two or more different values then you need to add a row inside the lowest group that will have all the required fields in either itself or child groups. As I guess I would say that would be the same level as your Total textbox. So Insert Row / Inside Group Above and then use the expression above but without the dataset name. You should be able to not specify this or if you get problems, specify it as the name of the rowgroup that your new textbox sits in.
To get an out of scope value, you can create custom code functions to store the value and assign the text as follows :
="Load Details" + Code.Save_TPLD_SYS_NO(Fields!TPLD_SYS_NO.Value)
When you need to recall the value at some other point you can reference a function that returns the saved value like:
=Code.GetSaved_TPLD_SYS_NO(true)
In your custom code you can create a variable that will hold the value and that the function would be something like:
NOTE : This is untested and the code comes from memory, you may have to fiddle a bit to get the correct syntax.
Public Dim Shared TPLD_SYS_NO As String ="";
function Save_TPLD_SYS_NO(value As String) As String
Begin
TPLD_SYS_NO = value
Return ""
End Function
function DisplayAndSave_TPLD_SYS_NO(value As String) As String
Begin
TPLD_SYS_NO = value
Return value
End Function
function GetSaved_TPLD_SYS_NO(resetValue as Boolean) As String
Begin
Dim result As String = TPLD_SYS_NO
If resetValue=true Then
TPLD_SYS_NO = ""
End If
Return result
End Function
Related
I have a report that has multiple parameters. The user will filter the data by inputting a value in to one of them.
All the parameters are created by the query and have the following design (fieldname = #param OR #param IS NULL)
In the parameter properties window, they have been changed to allow NULL values. The issue with this, is that the report renders initially with all data returned, as each parameter has the NULL checkbox ticked as default. From there you can input a value to one parameter and the report will filter as desired.
I would prefer the report not to render until one value has been given to one of the parameters. I am aware I can use a default value for one of the parameters, which would return no data, but this isn't ideal, as you still get the rendering of the report.
Is there a way to run the report but not render until a value is passed to one parameter?
-Write a custom code that checks the parameter value
Function GetReportCode(ParamVal AS String) As integer
Return IIf(ParamVal Is Nothing, 1/0, 0)
End Function
-If your parameter value is NULL then it will return an arithmetic overflow error
-Create a new variable with help of the following experision.
code.GetReportCode(Parameters!ReportParameter1.Value)
If the parameters takes NULL values it will return an error.
I have a database set up which includes a query and a form, which are causing me problems. In the form, I have a drop down menu which allows you to select from a list of ID values (e.g. 1, 2, 3, ...). Once you have selected a value, you then click a button and it runs the query with a parameter of the ID number from the drop down ([Forms]![KitInfoRetrievalForm]![DropDown]).
The problem here though, is that when I select something from the drop down menu and click the button to run the query, it gives a pop up box asking for a value to substitute in for [Forms]![KitInfoRetrievalForm]![DropDown]. This leads me to believe that either the drop down menu is a null value for some reason or my pathing to it is incorrect.
This was working at one point and then stopped after a series of weird error messages from something else entirely (in the same Access project). Any help you can give me would be much appreciated.
I would recommend to replace reference to dropdown in query by function. It should eliminate this problem and also this is a workaround for old bug in Access, which exists in all recent versions: if the form/subform is in datasheet mode and you applied filter (quick filter thru user interface or using VBA), it stops reading variables with references to controls or just parameters and uses last used value.
I'm using this function for reading form/subform control value:
Public Function GetControlValue(strFormName As String, strControlName As String, Optional strSubFormControlName As Variant) As Variant
On Error Resume Next
If IsMissing(strSubFormControlName) Then
GetControlValue = Forms(strFormName).Controls(strControlName).Value
Else
GetControlValue = Forms(strFormName).Controls(strSubFormControlName).Form.Controls(strControlName).Value
End If
End Function
In your case replace [Forms]![KitInfoRetrievalForm]![DropDown] by
GetControlValue("KitInfoRetrievalForm","DropDown")
On my application i have to search for an alphanumeric id which return one or more rows of data. On each of these rows a link is present i have to click on the first link.
Unfortunately it doesn't have any unique properties so i cannot add it to the OR. Instead i used descriptive programming something like below
'returns false
page.Link("class:=ng-binding","innertext:=AplhaID","html tag:=A").Exist
QTP fails to identify the object with the above code. So Instead of this i tried using Description object something like the below code
Set oDesc = Description.Object
oDesc("class").Value = "ng-binding"
oDesc("html tag").Value = "A"
oDesc("innertext").Value = "AplhaID"
Set lnk = page.ChildObjects(oDesc)
'gives me 2 which is correct. There are two links
msgbox lnk.Count
'highlights the correct link
lnk(0).Highlight
I do not know what could be causing this behavior. I thought is could be because multiple links match the description but I perform this search for multiple ids and eventhough multiple rows are returned the descriptive programming code is able to identify the correct row and proceed.
I looked at QTP descriptive programming issue but my link's property values do not have special characters.
In order to use Descriptive string method, ensure that you have only one object matching the given properties.
Below statement might fail if there are more than 1 object with the given properties.
page.Link("class:=ng-binding","innertext:=AplhaID","html tag:=A").Exist
So , you need to make the statement to find an object uniquely. Try this. It will work!
page.Link("class:=ng-binding","innertext:=AplhaID","html tag:=A", "index:=0").Exist
I am interested if it is possible to make variable name in PowerBuilder using a loop and a string. For example:
long ll_go
string lst_new
for ll_go = 1 to 8
lst_new = "text" + ll_go
lst_new.tag = 5500
next
So, it should give me variables text1, text2..,.,text8 and I would be able to assign values for them. Let me know if anybody succeeded, thanks in advance
Your description is lacking some term precision.
If you actually want to dynamically create new variables as "variable in a powerscript subroutine or function" this is simply not possible.
If instead you want to create dynamically some new controls statictext or textedit objects in a window or visual userobject this is possible:
use a local variable of the type of the new object you need to create, e.g. static text
make it a live object (instantiate) with create
set the object properties to whatever you need
"attach" the new object to its parent (either a window or a visual userobject - though any graphicobject is possible with using the win32api SetParent function) with the OpenUserObject() method. Note that you cannot simply add it directly to the parent's Control[] array.
you can also keep the object in your own array for later convenience access to the created objects instead of looping on the Control[] array
once the object is attached it its parent, you can reuse the local variable to create another one
Here is an example:
//put this in a button clicked() event on a window
//i_myedits is declared in instances variables as
//SingleLineEdit i_myedits[]
SingleLineEdit sle
int i
for i = 1 to 8
sle = create singlelineedit
sle.text = string(i)
sle.tag = "text_" + string(i)
sle.height = pixelstounits(20, ypixelstounits!)
sle.width = pixelstounits(100, xpixelstounits!)
parent.openuserobject(sle, pixelstounits(10, xpixelstounits!), pixelstounits(22 * i, ypixelstounits!))
i_myedits[i] = sle //keep our own reference
next
An exemple of values access:
//put that in another button clicked() event
SingleLineEdit sle
int i
string s_msg
for i = 1 to upperbound(i_myedits[])
sle = i_myedits[i]
if i > 1 then s_msg += "~r~n"
s_msg += "edit #" + string(i) + " (" + sle.tag + ") says '" + sle.text + "'"
next
messagebox("Edits values", s_msg)
As you can see, one practicality problem is that you cannot refer to these controls by constructing the control's name like "text"+2, instead you must access the my edits[] array or loop through the controls and test their .tag property if you set it to something specific.
I do not think that it is possible. Workaround could be an array maybe.
Br. Gábor
I'd see two ways to do this, but they aren't as easy as it seems that you were hoping:
1. Control Array
First method would be to go through the control arrays (on windows, tabs and user objects). I'd create a function that took the control name as a string, then another that overloaded the same function and took control name and an array of windowobject. The string-only method would just call the string/array method, passing the string through and adding the window.Control as the second parameter. The string/array method would go through the array, and for each element, get the ClassDefinition. Pull the name off of it, and parse it apart the way you want it to match the string parameter (e.g. for w_test`tab_first`tabpage_first`cb_here, do you want cb_here to match, or tab_first`tabpage_first`cb_here?). Deal with matches as appropriate. When you find a control of type tab or user object, call the string/array function again with the Control array from that object; deal with success/fail returns as appropriate.
2. DataWindow
What you're describing works extremely well with DataWindows, and their Describe() and Modify() functions. Since you pass these functions only a string, you can build not only the control names, but the values they're set to as you would build any string. In fact, you can build multiple Modify() strings together (delimited by a space) and make a single call to Modify(); this is not only faster, but reduces window flicker and visible activity.
Don't fall into the trap of thinking that, since your data isn't from a database, you can't use a DataWindow. Create an external DataWindow, and simply use it with one row inserted during the Constructor event.
As you might guess, I'd strongly favour the DataWindow approach. Not only is it going to perform better, but it's going to provide a lot more flexibility when you want to move on and tag more control types than just static text. (You'll have to do some type casting even with one control type, but if you want to get into multiples, you'll need to start a CHOOSE CASE to handle all your types.)
Good luck,
Terry
You can't create a variable name in a script because the variables have to be declared before you can use them. With PBNI it's possible to generate a name the way you describe and then get a reference to a variable of that name that already exists but I don't think that's what you want. If you want to keep track of additional properties for your controls, just inherit a new user object from whatever it is (sle, mle, etc.) and add the properties you want. Then you can place your user object on a window and use the properties. Another approach is to use the control's Tag property. It holds a string that you can put whatever you want in. PFC uses this technique. Terry's DataWindow solution is a good approach for storing arbitrary data.
Yes, and there are more than one way to skin a cat.
Sounds like you have several properties so I'd use an array of custom non visual user objects, or an array of structures. Otherwise you could probably use something from the .NET framework like a dictionary object or something like that, or a datawidnow using an external datasource, where you can refer to column names as col + ll_index.ToString().
SIMPLE Example:
Make custom NVO with following instance variables, plus getter/setter functions for each, name it n_single_field
// add the properties and recommend getter and setter functions
public string myTag
public string myText
public int myTabOrder
...
// To USE the NVO define an unbounded array
n_single_field fields[]
// to process the populated fields
integer li_x, li_max_fields
// loop through field 1 through max using array index for field number
li_max_fields = upperbound(fields)
for li_x = 1 to li_max_fields
fields[li_x].myTag = 'abc'
fields[li_x].myText = 'text for field number ' + li_x.ToString()
fields[li_x].myTabOrder = li_x * 10
next
Maybe I'm oversimplifying if so let me know, if there is a will there is always a way. ;)
Can you do this? The list filter I want to use looks like this:
Expression Operator Value
=Code.GetOccCat(Fields!accountnumber.Value) = =1
No dice. Basically, it acts like that function returns null as far as the filter is concerned, but when I take the filter off and put the exact same function call in a text box within the list, it returns what it's supposed to return. Can you just not do this, or what am I missing?
Edit: here's the function, completely simple:
Public Function GetOccCat(ByVal AccountNum As Integer) As Integer
Return OccCat(AccountNum)
End Function
OccCat is a public array of integers that is filled via an earlier function call. Again, the correct values display if I just put this in a text box, so the array is verified to be filling up correctly.
Edit: the array gets populated by way of a list at the top of the report. The list repeats on accountnumber with no filter. Inside the list is a textbox containing this code:
=Code.SetOccupancy(Fields!accountnumber.Value, First(Fields!new_total_hours.Value)/First(Fields!new_capacity.Value))
And here's that function:
Public Function SetOccupancy(ByVal AccountNum As Integer, ByVal Occ As Double) As String
Occupancy(AccountNum) = Occ
Select Occ
Case Is > .85
OccCat(AccountNum) = 1
Case .7 to .849
OccCat(AccountNum) = 2
Case .4 to .699
OccCat(AccountNum) = 3
Case Is < .4
OccCat(AccountNum) = 4
End Select
Return ""
End Function
FWIW, I've also tried this filter based on the Occupancy array (being > .85 in this case) and gotten the same result.
Could you show your function in your code?
I just checked it, and it certainly works to filter off of custom code. Though I didn't use yours exactly because I don't quite understand what you are trying to filter by.
Which field are you wanting to filter by?
I think you are just putting your code for your expression in the wrong place. Basically, put the field you want to filter by in the expression box that drops down. Then place your =code.getocccat(my value) in the value expression.
Try this and let me know, but it certainly works. I think you have the placement a little off.