Can I do CAST reference in ESQL? - websphere

While reproducing an example from IBM documentation: https://www.ibm.com/support/knowledgecenter/SSMKHH_9.0.0/com.ibm.etools.mft.doc/ak04864_.htm
with the following example message:
https://www.ibm.com/support/knowledgecenter/SSMKHH_9.0.0/com.ibm.etools.mft.doc/ak05911_.htm
without application of the message model,
on:
IBM Integration Toolkit Version: 10.0.0.16
with the following code fragment:
CALL CopyEntireMessage();
-- Declare the dynamic reference
DECLARE myref REFERENCE TO OutputRoot.XMLNSC.Invoice.Purchases.Item[1];
-- Continue processing for each item in the array
WHILE LASTMOVE(myref)=TRUE
DO
-- Add 1 to each item in the array
SET myref = CAST(myref AS INTEGER) + 1;
-- Move the dynamic reference to the next item in the array
MOVE myref NEXTSIBLING;
END WHILE;
I suddenly found out that the following line of code:
SET myref = myref + 1;
or alternatively:
SET myref = CAST(myref AS INTEGER) + 1;
did not have any effect on the value in the first item, and, even more, it was preventing expected work of:
MOVE myref NEXTSIBLING;
so that the myref pointer did not move to the next sibling (did not move from the item[1] to the item[2]) and myref was just disappearing from the list of variables in my debug view.
My question:
Any idea why SET myref = myref + 1; or SET myref = CAST(myref AS INTEGER) + 1; do not work? According to the document, the latter should work without the message model.

I cannot explain the symptoms, but I can make a couple of helpful suggestions:
Don't use counted loops in ESQL. It is almost always better to use a FOR loop to iterate over an array.
CALL CopyEntireMessage();
-- For each item in the array...
FOR refItem AS OutputRoot.XMLNSC.Invoice.Purchases.Item[] DO
SET refItem = CAST(refItem AS INTEGER) + 1;
END FOR;
No need to declare the reference variable (but you can if you want to, to stop the ESQL editor from complaining about the 'undeclared' reference variable).
No need to move the reference variable yourself - the FOR loop does it for you.
If you really want to know why your WHILE loop is not working...
You will find that the debugger only tells you what is happening. But (as you are finding out) it cannot tell you why it is happening. For that, you need a user trace. Not a Trace node, a user trace. You have to open the IIB console and use the mqsichangetrace, mqsireadlog, mqsiformatlog commands (in that order) to start user trace, read it and format it as text. It's a bit of hassle the first couple of times, but it will almost certainly show you why your code is not working.

Related

VB6, Adding an integer to a control name in a for loop

I am currently trying you learn VB6 and came across this issue.
I wanted to loop through a for loop and adding a number to a control name.
Dim I As Integer
For I = 1 To 5
S = CStr(I)
If TextS.Text = "" Then
LabelS.ForeColor = &HFF&
Else
LabelS.ForeColor = &H80000012
End If
Next I
This S needs to be added to Text and Label so the colour will be changed without needing to use 5 If Else statements
I hope you can help me with this.
From your comment below:
What i mean is this: If Text1.text = "" Then I need this 1 to be replaced with the variable I, so the for loop can loop through my 5 textboxes and the same for my Labels.
You can't do that (look up a variable using an expression to create its name) in VB6. (Edit: While that statement is true, it's not true that you can't look up form controls using a name from an expression. See "alternative" below.)
What you can do is make an array of your textboxes, and then index into that array. The dev env even helps you do that: Open your form in the dev env and click the first textbox. Change its name to the name you want the array to have (perhaps TextBoxes). Then click the next textbox and change its name to the same thing (TextBoxes). The dev env will ask you:
(Don't ask me why I have a VM lying around with VB6 on it...)
Click Yes, and then you can rename your other textboxes TextBoxes to add them to the array. Then do the same for your labels.
Then your code should look like this:
For I = TextBoxes.LBound To TextBoxes.UBound
If TextBoxes(I).Text = "" Then
Labels(I).ForeColor = &HFF&
Else
Labels(I).ForeColor = &H80000012
End If
Next
LBound is the lowest index of the control array, UBound is the highest. (You can't use the standard LBound and Ubound that take the array as an argument, because control arrays aren't quite normal arrays.) Note also that there's no need to put I on the Next line, that hasn't been required since VB4 or VB5. You can, though, if you like being explicit.
Just make sure that you have exactly the same number of TextBoxes as Labels. Alternately, you could create a user control that consisted of a label and a textbox, and then have a control array of your user control.
Alternative: : You can use the Controls array to look up a control using a name resulting from an expression, like this:
For I = 1 To 5
If Me.Controls("Text" & I).Text = "" Then
Me.Controls("Label" & I).ForeColor = &HFF&
Else
Me.Controls("Label" & I).ForeColor = &H80000012
End If
Next
This has the advantage of mapping over to a very similar construct in VB.Net, should you migrate at some point.
Side note:
I am currently trying you learn VB6...
(tl;dr - I'd recommend learning something else instead, VB6 is outdated and the dev env hasn't been supported in years.)
VB6's development environment has been discontinued and unsupported for years (since 2008). The runtime is still (I believe) supported because of the sheer number of apps that use it, although the most recent patch seems to be from 2012. But FWIW, you'd get a better return on your study time learning VB.net or C#.Net (or any of several non-Microsoft languages), rather than VB6...

Obtaining a reference to a NotesView with NotesDatabase.Views(x) can be surprisingly slow

In VB6, I'm supporting code that loops through all the views in a Lotus Notes database thusly:
For lngdomViewidx = LBound(domDatabase.Views) To UBound(domDatabase.Views)
Set domView = domDatabase.Views(lngdomViewidx) ' note: this line right here is slow to execute
The amount of time it takes to retrieve a reference to the view by index with this method seems proportional to the number of documents in the view. This bit of code is just looping through the Notes database to build a list of all the view names. On really large databases this can take several minutes. Is there a faster way to get this information?
Thanks!
That is not a very efficient way, no.
Use something like the code below instead. It is Lotusscript, but it should be pretty much the same in VB. I haven't tested it, just copied it from a production database and modified it to look for views instead for forms like in my original...
Dim ncol As NotesNoteCollection
Set ncol = db.CreateNoteCollection(True)
Call ncol.SelectAllNotes(False)
ncol.SelectViews = True
Call ncol.BuildCollection
noteID = ncol.GetFirstNoteId
For i = 1 To ncol.Count
Set doc = targetdb.GetDocumentByID(noteID)
MsgBox "view = " + doc.GetItemValue("$Title")(0)
noteID = ncol.GetNextNoteId(noteID)
Next
Karl-Henry is absolutely right: The NotesNoteCollection is really the fastest way to loop through all views.
But you can speed up your code significantly by just changing the loop.
Instead of opening each view using its index, you coud, do something like:
Forall view in db.Views
'Do whatever you want
End Forall
Accessing elements in a collection in Lotus Notes using the index means, that it always has to count from the beginning, while using a forall- loop directly accesses the next element...

For loop in VBScript (QTP) not functioning

I'm using QTP 11.0 which uses VBScript for it's "language".
I have the following four lines of code:
For x = 1 to 8
msgbox(x)
update1 = SwfWindow("NextGen File Maintenance").SwfWindow("SIM Library Configuration").SwfObject("spreadCtl").Object.ActiveSheet.GetValue(x,2)
Next
The return values are:
1
3
3
3
3
3
... forever
I can not seem to use the counter variable in a vbscript for loop without it somehow becoming corrupted - no matter what the name of the variable. I have even tried assigning X to another variable and using that in my GetValue statement with no success.
Am I missing something really simple here? No documentation on Google for a vbscript For loop implies any different usage. I found nothing in reference to QTP either.
Thanks,
Jason
This is very strange, I assume that if you remove the second line in the loop and just leave the MsgBox then x is incremented correctly.
Perhaps ActiveSheet.GetValue takes the first parameter by reference and modifies it. You say that you tried using a temporary variable and it didn't work, have you tried something like this?
For x = 1 to 8
tmp = x
update1 = SwfWindow("NextGen File Maintenance").SwfWindow("SIM Library Configuration").SwfObject("spreadCtl").Object.ActiveSheet.GetValue(tmp, 2)
MsgBox("x=" & x & " tmp=" & tmp)
Next
If the problem is that GetValue indeed changes the index you can try using a function that takes the index by value and then use that in the loop.
Public Function GetVal(ByVal index)
GetVal = SwfWindow("NextGen File Maintenance").SwfWindow("SIM Library Configuration").SwfObject("spreadCtl").Object.ActiveSheet.GetValue(index, 2)
End Function

VHDL integer'image Returns "0"

Here is my dilemma:
I'm very new to programming in VHDL, and I'm currently working on an independent study project for a university class. I've made some descent headway, but I've run into an issue I haven't been able to solve.
What I'm trying to do is to display a "register" (or registers) on an LCD monitor and have it update periodically. For the time being, these values will always be integer numbers.
I have code written which displays numbers properly on the screen if that value is passed as a variable that is never altered or as a hard-coded value. However, I want to update a variable by adding to it, then pass that to my function and display it.
Essentially what I'm trying to do is this:
Every 'x' clock ticks, increment a register's value, pass that to my update_screen function which returns a new screen, and then display that further below. However, once I increment or change through reassignment (doesn't seem to matter if it is variable or a signal), all I see is '0' on the screen.
So... The following code properly updates my display unless I uncomment the commented lines. At that point, it just shows '0'.
--currentRegVal := currentRegVal + 1;
--screenVal <= 25;
-- screen holds the values for the current screen
-- The second argument is the row on the screen to be updated
-- The third argument is the value to display there
screen := update_screen(screen, 1, currentRegVal);
screen := update_screen(screen, 0, screenVal + 25);
The problem seems to be stemming from the integer'image attribute (or more accurately, my understanding of it). When I pass in a hardcoded value or a variable that hasn't been altered, it returns what I expect. However, as soon as I modified the variable/signal in ANY way it seems to return the string "0".
Below is my update_screen function:
function update_screen(screen: screenData; reg, regVal: integer) return screenData is
-- A function may declare local variables. These do not retain their values between successive calls,
-- but are re-initialised each time. Array-type parameters may be unconstrained:
constant screenWidth: integer := screen'length(2);
constant strRegVal: string := integer'image(regVal);
constant strRegLen: integer := strRegVal'length;
variable newScreen: screenData := screen;
begin
for dex in 1 to screenWidth loop
if dex <= strRegLen then
newScreen(reg, dex-1) := strRegVal(dex);
else
newScreen(reg, dex-1) := ' ';
end if;
-- The next two ifs were my attempt to figure out what
-- was going on...
--The value itself never seems to be 0... the screen is not all 5's
if regVal = 0 then
newScreen := (others => (others => '5'));
end if;
-- But the string value is "0" if the variable/signal is ever modified...
-- 'd' shows up in the designated row.
if strRegVal = "0" then
newScreen(reg*3, 1) := 'd';
end if;
end loop;
return newScreen;
end update_screen;
A couple important points (added 2011-07-26):
I'm using the Quartus II free (web) edition to design/compile my project.
The code which is updating the variables is in a process.
At the time of the original posting, the only steps I had taken were to compile my code and program an Altera DE2 FPGA board with the result (I wasn't sure how to perform any kind of simulations).
Thanks in advance for any help and advice. Also, as I said, I'm new to VHDL programming, so if there is a much better way to do something I'm doing here, please let me know. I would also greatly appreciate useful links to any resources about the language itself.
Update (2011-07-26):
I downloaded GHDL as Martin Thompson suggested, but I have not actually used it yet because I'm not sure how to go about doing so with my current Quartus II project (or if I even can). I'll have to do some reading before it is useful to me. However, yesterday I managed to install ModelSim-Altera which works directly with Quartus II and allowed me to perform some simulation.
I did my best to set up some waveforms that would allow me to test, and I was at least able to examine the execution of the code which I believed to be failing. However, during simulation, I've verified in multiple ways that the "screen" object does contain the value I want it to contain after the *screen_update* function runs. When running on the Altera DE2, however, it still fails.
Note: I did verify that the screen actually does update by directly setting the value of a particular element on the screen to different values depending on whether or not the currentRegVal is even or odd.
I'll plan on posting some code tomorrow, but for now:
What reasons are there that simulation would provide different results? My guess is something to due with timing, but it is really just a guess. If I am correct, how can I go about trying to resolve the issue?
I guess the problem is related to the fact that you declared strRegVal as a constant. I think it should better be a variable, e.g. something like this might work:
function update_screen(screen: screenData; reg, regVal: integer) return screenData is
...
variable strRegVal: string;
variable strRegLen: integer;
...
begin
strRegVal := integer'image(regVal);
strRegLen := strRegVal'length;
...
end update_screen;
Assuming this code is in a process:
screenVal <= 25;
-... snip...
screen := update_screen(screen, 0, screenVal + 25);
screenVal won't have updated to a new value yet (unless some time passes - a wait statement between the write and the read)

VB6 control iteration: one control gives me an error; which one?

I am trying to loop through all controls in a form:
For Each ctrl in Me.Controls
in order enable/disable the control based on some conditions.
But there is a control on the form that gives an error when I try to access it. What kind of control does that, and how do I find it?
When you get your error and click Debug, is the error on the line setting a control's Enabled property?
If so, add a Debug.Print statement writing out the control's name. Do so on the line before setting the Enabled property.
Here's what I mean:
Dim ctrl As Control
For Each ctrl In Me.Controls
Debug.Print ctrl.Name
ctrl.Enabled = True
Next
The Debug.Print statement will write out to the Immediate Window the name of the control that was last processed in the loop, presumably the one that caused your error.
EDIT
This might work. Put this control in a Panel control and set the Panel's Enabled property to False. If I recall correctly, in VB6 setting a container control's Enabled property to False will also set the container's child controls Enabled to False. If your control's Enabled property really is read-only, I'm curious what would happen.
Try this:
Dim ctr As Control
Dim CtrStatus Boolean
CtrStatus = False
For Each ctr In Me.Controls
If (SSTab.hwnd = GetParent(ctr.hwnd)) Then
Call CallByName(ctr, "Enabled", VbLet, CtrStatus)
else
ctr.Enabled = CtrStatus
End If
Next
Another approach is as follows, that also works at runtime (as opposed to just in the IDE):
private sub SetEnabled()
on error goto errHandle
Dim ctrl As Control
For Each ctrl In Me.Controls
ctrl.Enabled = True
Next
exitPoint:
exit sub
errHandle:
MsgBox "Error " & err.Description & " with Control " & ctrl.Name
resume exitPoint
end sub
Suppress the error reports before the loop and then set it back to standard error handling:
On Error Resume Next
For Each ctrl In Me.Controls
ctrl.Enabled = lIsEnabled
Next
On Error GoTo 0
OR name your controls with a standard prefix/suffix that you can check by name and skip in the loop.
For Each ctrl In Me.Controls
If Left(ctrl.Name, 3) = "sst" Then
ctrl.Enabled = lIsEnabled
End If
Next
Tosa: from your comment on AngryHacker's answer, I think you are checking the container incorrectly.
Your code is like this
' BAD CODE '
If ctrl.Container = fraMovies Then
For me that gives error 450 Wrong number of arguments or invalid property assignment. Do you get the same error?
The code should use Is rather than =, like this
' GOOD CODE '
If ctrl.Container Is fraMovies Then
Explanation. You want to check whether two variables "point" to the same control. Controls are objects: you must use Is not = to check whether two object variables "point" to the same object. This is a classic pitfall in VB6.
One last word. Next time, could you try to post 10 lines or less of actual code, reproducing the error, and give the exact error number and message and the exact line on which it occurs? It really does make it much easier for us to solve your problem - I know it's work for you to shorten the code, but you'll get better answers that way.
EDIT Welcome back! :) You said some controls don't have a Container property. You could try wrapping the test in On Error Resume Next, something like this.
' GOOD CODE '
Dim bMatch As Boolean
Dim ctrl As Control
For Each ctrl In Me.Controls
bMatch = False
On Error Resume Next
bMatch = (ctrl.Container Is fraMovies)
On Error Goto 0
If bMatch Then
ctrl.Enabled = True
End If
Next
To avoid such problems follow the given rules while naming contols
When you name an element in your Visual Basic application, the first character of that name must be an alphabetic character or an underscore.
**Begin each separate word in a name with a capital letter, as in FindLastRecord and RedrawMyForm.
Begin function and method names with a verb, as in InitNameArray or CloseDialog.
Begin class, structure, module, and property names with a noun, as in EmployeeName or CarAccessory.
Begin interface names with the prefix "I", followed by a noun or a noun phrase, like IComponent, or with an adjective describing the interface's behavior, like IPersistable. Do not use the underscore, and use abbreviations sparingly, because abbreviations can cause confusion.
Begin event handler names with a noun describing the type of event followed by the "EventHandler" suffix, as in "MouseEventHandler".
In names of event argument classes, include the "EventArgs" suffix.
If an event has a concept of "before" or "after," use a suffix in present or past tense, as in "ControlAdd" or "ControlAdded".
For long or frequently used terms, use abbreviations to keep name lengths reasonable, for example, "HTML", instead of "Hypertext Markup Language". In general, variable names greater than 32 characters are difficult to read on a monitor set to a low resolution. Also, make sure your abbreviations are consistent throughout the entire application. Randomly switching in a project between "HTML" and "Hypertext Markup Language" can lead to confusion.
Avoid using names in an inner scope that are the same as names in an outer scope. Errors can result if the wrong variable is accessed. If a conflict occurs between a variable and the keyword of the same name, you must identify the keyword by preceding it with the appropriate type library. For example, if you have a variable called Date, you can use the intrinsic Date function only by calling DateTime.Date.

Resources