Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Do Until Loop Syntax

Status
Not open for further replies.

ej2rms13

Technical User
Dec 11, 2017
10
US
Hi, I am having some issue with my code. I am going through attachmate since this is the application my coworkers and I use the most. This is the last piece of the puzzle (apart from exporting some of the results to excel) for this code and I am at a loss here. It will give me syntax if I put parenthesis around Until and an error code saying it doesnt recognize whats going on on line 54 (highlighted) if I exclude the parenthesis. Any help is appreciated. Here is my code:

Code:
' Global variable declarations
Global g_HostSettleTime%
Global g_szPassword$

Sub Main()
'--------------------------------------------------------------------------------
' Get the main system object
	Dim Sessions As Object
	Dim System As Object
        Dim n As Integer
        n = 6
	Set System = CreateObject("EXTRA.System")	' Gets the system object
	If (System is Nothing) Then
		Msgbox "Could not create the EXTRA System object.  Stopping macro playback."
		STOP
	End If
	Set Sessions = System.Sessions

	If (Sessions is Nothing) Then
		Msgbox "Could not create the Sessions collection object.  Stopping macro playback."
		STOP
	End If
'--------------------------------------------------------------------------------
' Set the default wait timeout value
	g_HostSettleTime = 3000		' milliseconds

	OldSystemTimeout& = System.TimeoutValue
	If (g_HostSettleTime > OldSystemTimeout) Then
		System.TimeoutValue = g_HostSettleTime
	End If

' Get the necessary Session Object
	Dim Sess0 As Object
	Set Sess0 = System.ActiveSession
	If (Sess0 is Nothing) Then
		Msgbox "Could not create the Session object.  Stopping macro playback."
		STOP
	End If
	If Not Sess0.Visible Then Sess0.Visible = TRUE
	Sess0.Screen.WaitHostQuiet(g_HostSettleTime)
 

	
' This section of code contains the recorded events


       [highlight #FCE94F] Do Until Sessions.WaitForString("NO PART SELECTED", 23, 2, 16)[/highlight]
        
   

	Sess0.Screen.Sendkeys("<Clear>/for ESEOU04<Enter>1q<Enter>")	
	Sess0.Screen.WaitHostQuiet(g_HostSettleTime)
 
        If n = 23 Then
        Sess0.Screen.Sendkeys("<Enter>")
        n = 6                                       'resets integer
        Sess0.Screen.Area(n, 9, n, 16).select
	Sess0.Screen.Area(n, 9, n, 16).copy	
	Sess0.Screen.Sendkeys("<Pf5>")	
	Sess0.Screen.WaitHostQuiet(g_HostSettleTime)
	Sess0.Screen.MoveTo 3, 15
        Sess0.Screen.Paste	
	Sess0.Screen.Sendkeys("<Enter>")
        Sess0.Screen.WaitHostQuiet(g_HostSettleTime)
        Exit Do
        
        Else
        Sess0.Screen.Area(n, 9, n, 16).select
	Sess0.Screen.Area(n, 9, n, 16).copy	
	Sess0.Screen.Sendkeys("<Pf5>")	
	Sess0.Screen.WaitHostQuiet(g_HostSettleTime)
	Sess0.Screen.MoveTo 3, 15
        Sess0.Screen.Paste	
	Sess0.Screen.Sendkeys("<Enter>")
        Sess0.Screen.WaitHostQuiet(g_HostSettleTime)
        Exit Do
        
        End If
 
 
 	If Found1st Then
        Found = Sessions.WaitForString("", 10, 74)
        Sess0.Screen.WaitHostQuiet(g_HostSettleTime)
        Sess0.Screen.MoveTo 4, 15
        Sess0.Screen.Sendkeys(" ")                  'removed c for testing
        Sess0.Screen.Area(10, 74, 10, 75).select
	Sess0.Screen.Area(10, 74, 10, 75).copy
        Sess0.Screen.MoveTo 5, 15
        Sess0.Screen.Paste
        Sess0.Screen.Area(11, 73, 11, 80).select
	Sess0.Screen.Area(11, 73, 11, 80).copy
        Sess0.Screen.MoveTo 6, 15
        Sess0.Screen.Paste
        Sess0.Screen.MoveTo 12, 15
        Sess0.Screen.Sendkeys("n")
        Sess0.Screen.Sendkeys("<Enter>")
        Sess0.Screen.Sendkeys("<Enter>")
        
        
        ElseIf Found2nd Then
        Found = Sessions.WaitForString("N", 10, 74)
        Sess0.Screen.WaitHostQuiet(g_HostSettleTime)
        Sess0.Screen.MoveTo 4, 15
        Sess0.Screen.Sendkeys(" ")                  'removed c for testing
        Sess0.Screen.Area(10, 74, 10, 75).select
	Sess0.Screen.Area(10, 74, 10, 75).copy
        Sess0.Screen.MoveTo 5, 15
        Sess0.Screen.Paste
        Sess0.Screen.Area(11, 73, 11, 80).select
	Sess0.Screen.Area(11, 73, 11, 80).copy
        Sess0.Screen.MoveTo 6, 15
        Sess0.Screen.Paste
        Sess0.Screen.MoveTo 12, 15
        Sess0.Screen.Sendkeys("n")
        Sess0.Screen.Sendkeys("<Enter>")
        Sess0.Screen.Sendkeys("<Enter>")
        
        Else
        n = n + 1
        
        
        End If
        
        Loop 
        
	System.TimeoutValue = OldSystemTimeout
End Sub
 
Hi,

Code:
 Do Until [highlight #FCE94F]Sess0.Screen[/highlight].WaitForString("NO PART SELECTED", 23, 2, 16)

Skip,
[sub]
[glasses]Just traded in my OLD subtlety...
for a NUance![tongue][/sub]
 
Thank you for your reply Skip! After some adjusting I was able to get the code working how I want it however it seems to take about 5-10 seconds to loop back to the beginning. Any insight as to how I can speed this up?

Thanks
 
I never found wait techniques like Sess0.Screen.WaitHostQuiet(g_HostSettleTime) very satisfactory.

Rather, I have used WaitForCursor() with satisfactory results...
Code:
'Insert this technique after each command is sent to the mainframe
'  where r, c are the Screen Rest Coordinates
'  Loop waits for mainframe to complete and restore the screen to its complete state
'  at the rest coordinates.

   Sess0.Screen.MoveCursor r+1, c+1            'move the cursor away from the rest coordinates
   Do Until Sess0.Screen.WaitForCursor(r, c)
      DoEvents
   Loop

The only other thing you might want to add is a Timeout ejector,that if the mainframe does not respond within a reasonable duration that the routine aborts.

Skip,
[sub]
[glasses]Just traded in my OLD subtlety...
for a NUance![tongue][/sub]
 
Hi Skip,

I've been working on and off this code for a while. I tried replacing all the WaitForQuietHost with WaitForCursor and this did not help. I believe the pause that I am enduring between the end of one loop and the other starting is this line of code:

Do Until Sess0.Screen.WaitForString("NO PART SELECTED", 23, 2, 16)

whenever I step through it, it always gives me a considerable pause. It could be the waitforstring command. Is there an alternative to this?

Thanks
 
WaitForString is another valid alternative to wating a fixed duration.

You’re dealing with a terminal EMULATOR. There are all sorts of factors that could affect the performance of the emulator software, that would bear on the delay between the mainframe competing an exchange of data with the emulator and your code detecting either the cursor at the rest coordinates for that particular screen or the appearance of a string at given coordinates.

There are other WaitFor... methods that you could reseach and experiment with. Look at your programmer’s reference. That’s what I did some 15 years ago when I was scaping screens from an Excel list to an Excel table, at the best possible rate. First off, I did ALL my coding and execution in Excel, since my source data was ALWAYS in Excel and my result table was ALWAYS in Excel for my customers. Consequently, my experimenting lead me to use WaitForCursor as being the most reliable: 1) not missing data from my input list and 2) running at a reasonable rate. In Excel I’d use Application.ScreenUpdating = FALSE to get max speed.

Skip,
[sub]
[glasses]Just traded in my OLD subtlety...
for a NUance![tongue][/sub]
 
I should have gone back to read the previous posts.

1) Remove all other STATIC Wait statements like Sess0.Screen.WaitHostQuiet(g_HostSettleTime)!!!

2) After ANY process command (PFx,ENTER etc) this is where a Do...Loop like this needs to be inserted INSTEAD of Sess0.Screen.WaitHostQuiet(g_HostSettleTime).
Code:
‘
        Sess0.Screen.Sendkeys("<Pf5>")	
	[s]Sess0.Screen.WaitHostQuiet(g_HostSettleTime)[/s]
         Sess0.Screen.MoveCursor r+1, c+1            'move the cursor away from the rest coordinates
         Do Until Sess0.Screen.WaitForCursor(r, c)
            DoEvents
         Loop

Skip,
[sub]
[glasses]Just traded in my OLD subtlety...
for a NUance![tongue][/sub]
 
Skip,

Maybe I am not understanding waitforcursor in this application. For my application, the cursor will reside in the same position for the majority of the execution of the code. Let me provide another code I wrote as example (this is basically a rough draft however it works).

Code:
Sub Main()
'--------------------------------------------------------------------------------
' Get the main system object
    Dim Sessions As Object
    Dim System As Object
    Dim R As Long
    Set System = CreateObject("EXTRA.System")   ' Gets the system object
    If (System Is Nothing) Then
        MsgBox "Could not create the EXTRA System object.  Stopping macro playback."
        Stop
    End If
    Set Sessions = System.Sessions
    
    R = 3

    If (Sessions Is Nothing) Then
        MsgBox "Could not create the Sessions collection object.  Stopping macro playback."
        Stop
    End If
'--------------------------------------------------------------------------------
' Set the default wait timeout value
    g_HostSettleTime = 3000     ' milliseconds

    OldSystemTimeout& = System.TimeoutValue
    If (g_HostSettleTime > OldSystemTimeout) Then
        System.TimeoutValue = g_HostSettleTime
    End If

' Get the necessary Session Object
    Dim Sess0 As Object
    Set Sess0 = System.ActiveSession
    If (Sess0 Is Nothing) Then
        MsgBox "Could not create the Session object.  Stopping macro playback."
        Stop
    End If
    If Not Sess0.Visible Then Sess0.Visible = True
    Sess0.Screen.WaitHostQuiet (g_HostSettleTime)
    
' This section of code contains the recorded events
    Sess0.Screen.SendKeys ("<Clear>")
        Sess0.Screen.WaitForCursor 1, 1
    Sess0.Screen.SendKeys ("/for EEAOI01")
        Sess0.Screen.SendKeys (" <Enter>")
        
        Range("B2").Select
    Selection.Copy
    
   
    
    Sess0.Screen.Paste
    Sess0.Screen.WaitHostQuiet (g_HostSettleTime)
    Sess0.Screen.SendKeys ("<Enter>")
   Sess0.Screen.WaitHostQuiet (g_HostSettleTime)
   
   Sess0.Screen.MoveTo 3, 51
   Sess0.Screen.SendKeys ("n")
    Sess0.Screen.MoveTo 4, 51
   Sess0.Screen.SendKeys ("n")
   Sess0.Screen.MoveTo 5, 13
   Sess0.Screen.SendKeys ("s")
   Sess0.Screen.SendKeys ("<Enter>")
   Sess0.Screen.WaitHostQuiet (g_HostSettleTime)
   Sess0.Screen.MoveTo 5, 13
   Sess0.Screen.SendKeys ("m")
   Sess0.Screen.SendKeys ("<Enter>")
   Sess0.Screen.WaitHostQuiet (g_HostSettleTime)
   
   
 '------------------------------------------------------------------
 'This is where the copying and pasting happens
 '------------------------------------------------------------------
 Do Until Sess0.Screen.WaitForString("END OF ASSEMBLY", 23, 22, 15)
'Part numbers
    Sess0.Screen.Area(8, 13, 22, 20).Select
    Sess0.Screen.Area(8, 13, 22, 20).Copy
    
   Cells(R, 2).Select
    ActiveSheet.Paste
    
'Indent lvl
    Sess0.Screen.Area(8, 10, 22, 11).Select
    Sess0.Screen.Area(8, 10, 22, 11).Copy
    
   Cells(R, 1).Select
    ActiveSheet.Paste
    
'qty
    Sess0.Screen.Area(8, 23, 22, 24).Select
    Sess0.Screen.Area(8, 23, 22, 24).Copy
    
   Cells(R, 3).Select
    ActiveSheet.Paste
    
'Service Code
    Sess0.Screen.Area(8, 26, 22, 27).Select
    Sess0.Screen.Area(8, 26, 22, 27).Copy
    
   Cells(R, 4).Select
    ActiveSheet.Paste
    
'FSU
    Sess0.Screen.Area(8, 29, 22, 36).Select
    Sess0.Screen.Area(8, 29, 22, 36).Copy
    
   Cells(R, 5).Select
    ActiveSheet.Paste
    
'UPC
    Sess0.Screen.Area(8, 41, 22, 45).Select
    Sess0.Screen.Area(8, 41, 22, 45).Copy
    
   Cells(R, 6).Select
    ActiveSheet.Paste
    
'FNA
    Sess0.Screen.Area(8, 47, 22, 51).Select
    Sess0.Screen.Area(8, 47, 22, 51).Copy
    
  Cells(R, 7).Select
    ActiveSheet.Paste
    
'Description
    Sess0.Screen.Area(8, 53, 22, 75).Select
    Sess0.Screen.Area(8, 53, 22, 75).Copy
    
   Cells(R, 8).Select
    ActiveSheet.Paste
    
'Next Page
Sess0.Screen.SendKeys ("<Enter>")
   Sess0.Screen.WaitHostQuiet (g_HostSettleTime)
   R = R + 15
    Sess0.Screen.WaitHostQuiet (g_HostSettleTime)
    
    
    Loop
    
    System.TimeoutValue = OldSystemTimeout
End Sub

Basically this code is pulling information from Attachmate and pasting into Excel as I am sure you can clearly see. There are usually 20+ pages of info that I pull from Attachmate, hitting ENTER is how I access the next page. On the last page ENTER can be pressed again to start from the first page so I must rely on waitforstring since the cursor is always in the same position.
 
Im guessing I cannot avoid the waitforstring in my particular application. The only other idea I have is to copy and paste the code within the loop a couple times so that it speeds up the execution. [dazed]
 
You need to adjust your understanding of how your system works. In front of you, you have your monitor for your PC or laptop. Under normal circumstances, you ENTER something or push a button with your mouse and something immediately happens on YOUR SYSTEM.

However, now you have some OTHER SYSTEM, maybe an IBM mainframs out there somewhere, where the users previously had a dumb terminal & keyboard, but now, due to PCs and all the software we can run on them, we can make the PC monitor and keyboard act like an IBM dumb terminal/keyboard. We refer to that as an emulator. So the Attachmate company started manufacturing terminal emulator software, so that users could throw away the dumb terminal/keyboard next to the PC they had added on top of their desks because PCs were becoming THE computer office tool. And everybody was happyer doing their mail and spreadsheet and precentations and Getting data in and out of the mainframe all on one device.

But, of course, we want to go faster and do more so many applications made provision for coding and macros and the like. But here’s the rub: the IBM system is “out there” and not like your PC system. In your PC system, when its busy, the whole thng slows down and that spinner spins and you eventually go get some coffee. However, your PC has no idea in the world what’s going on in Big Blue. Nada! So if you SendKeys some PF key command, you have no guarantee of when the mainframs will respond. Could be right away, as it most often is, or a second or a minute or an hour or maybe the system is down. ??? Dunno!

Now if you decide to Sess0.Screen.WaitHostQuiet (g_HostSettleTime) each time you SendKeys command, it would be like deciding before you left for work in the morning, that each time you came to an intersection, you would WaitFiveSeconds and then cross the street without any regard for the traffic that might impinge on your progress. If you’re driving, there might be instances where there is no traffic and consequently no need to even stop. However, there will be other instances where there is a stop/go signal, and you must heed the signal before proceeding. In other instances, you might need to stop and evaluate the traffic conditions in and around the intersection. In an yet another instance, where no intersection exists but traffic does, you will have yet another stop, go and speed evaluations.

So what I’m suggesting is that when you SendKeys command, your program must WAIT for a SIGNAL from the mainframe that it’s ready to proceed. The SIGNAL that I’ve used most successfully is WaitForCursor. The way that the emulator works, when you SendKeys command, the cursor goes away until the mainframe is ready, when it returns.

Skip,
[sub]
[glasses]Just traded in my OLD subtlety...
for a NUance![tongue][/sub]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top