alexm963

_ArrayDisplay that doesn't pause the script

7 posts in this topic

Ok, hopefully the title explains what I'm looking for pretty clearly. At the end of my script I display an array generated from a Oracle DB query. However in certain applications I want a different document as the active window at the end of the script (i.e. Word, Excel, PDF).

I need the array to still be open and viewable. Is there a way to get rid of the script pausing caused by _arraydisplay? Is there a different function I can use to accomplish this?

I'm assuming my code isn't needed for this but feel free to ask for it. 

Thanks. 

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

@alexm963 a couple of things:

  • Sharing your code is always beneficial when asking a question - people are a lot more likely to help if they don't have to guess at just what you're doing, or retype a long script.
  • _ArrayDisplay was originally intended as a debugging tool (though there has been some debate on the forum on whether that is all it should be used for). For a live situation where you want to display information - and especially when you don't want it to be script blocking - you can create a small GUI to accomplish this, like so:
#include <Array.au3>
#include <GUIConstantsEx.au3>
#include <GuiListView.au3>
#include <MsgBoxConstants.au3>

Local $aArray[19] = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", _
                     "January", "February", "March", "April", "May", "June", "July", "August", _
                     "September", "October", "November", "December"]
Local $hGUI = GUICreate("Test", 300, 300)
Local $hView = GUICtrlCreateListView("My Array", 10, 10, 200, 280)
    For $element In $aArray
        GUICtrlCreateListViewItem($element, $hView)
    Next

GUISetState(@SW_SHOW)

    MsgBox($MB_OK, "", "See! Not blocked!")

    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                Exit
        EndSwitch
    WEnd

   This is a pretty rough example (look at  _GUICtrlListView_AddArray in the help file to add an entire array), but gives you an idea of just one way you could get around this issue.

Edited by JLogan3o13

√-1 2^3 ∑ π, and it was delicious!

Share this post


Link to post
Share on other sites

alexm963,

You will have to create your own GUI to display the array. This is not as difficult as it sounds as you are generating the array yourself and so you should have a fairly good idea of what layout will be required. The existing _ArrayDisplay code should give you a good idea of how you might proceed - I know it looks complicated, but a lot of it is there to deal with whatever type of array the user throws at it and so can be discarded.

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

One way to get around the problem is to run _ArrayDisplay in a new process and then transfer the array to the new process through a system global object created with AutoItObject:

#include <GUIConstantsEx.au3>
#include <AutoItObject.au3>

Example()

Func Example()
  _AutoItObject_StartUp()

  ; Register object to transfer data
  Local $sDataTransferObject = "DataTransferObject"
  Local $oDataTransferClass, $oDataTransferObject, $hDataTransferObject
  $oDataTransferClass = _AutoItObject_Class()
  $oDataTransferClass.AddProperty( "ArrayData" )
  $oDataTransferObject = $oDataTransferClass.Object
  $hDataTransferObject = _AutoItObject_RegisterObject( $oDataTransferObject, $sDataTransferObject )

  ; Create array
  Local $aArray[1000][8]
  For $i = 0 To 1000 - 1
    For $j = 0 To 7
      $aArray[$i][$j] = $i & "/" & $j
    Next
  Next

  ; Transfer data
  $oDataTransferObject.ArrayData = $aArray

  ; Open ArrayDisplay script
  Local $iPID =  ShellExecute( "Display.au3" )

  GUICreate("Example", 300, 200, 100, 100)
  Local $idButton = GUICtrlCreateButton("Button", 105, 85, 90, 30)
  GUISetState(@SW_SHOW)

  While 1
    Switch GUIGetMsg()
      Case $idButton
        MsgBox( 0, "", "" )
      Case $GUI_EVENT_CLOSE
        ExitLoop
    EndSwitch
  WEnd

   If $iPID Then ProcessClose($iPID)

  ; Unregister data transfer object
  _AutoItObject_UnregisterObject( $hDataTransferObject )

  _AutoItObject_Shutdown()
EndFunc

Display.au3:

#include <Array.au3>

Example()

Func Example()
  ; Data transfer object
  Local $sDataTransferObject = "DataTransferObject"
  Local $oDataTransferObject = ObjGet( $sDataTransferObject )

  ; Get array
  Local $aArray = $oDataTransferObject.ArrayData

  _ArrayDisplay( $aArray )
EndFunc

 

Edited by LarsJ
1 person likes this

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

Ok I think I understand that now. I have been able to generate a GUI that displays the array. However, I am creating the GUI within a function. Then calling a separate function after it is displayed. Now the Gui will appear, but then close as soon as the second function runs. I need the GUI to live even after the function has completed. 

$PN = _NewSO()

_BOM($PN)

_OpenDoc($PN, "1")
_OpenDoc($PN, "F")


Func _NewSO()

    WinClose("Bill of Materials")

    $sON = InputBox("Shop Order Number", "Scan or enter the Shop Order Number you would like to build.", "", " M")
    If @error = 1 Then Exit

    If _Singleton(@ScriptName, 1) = 0 Then ;~~ This function checks for a single instance of the script and will kill any previous instances ~~
        $KillList = ProcessList(@ScriptName)
        For $i = 1 To $KillList[0][0]
            If $KillList[$i][1] <> @AutoItPID Then ProcessClose($KillList[$i][1])
        Next
    EndIf

;~~ These loops will close all open documentation
    Do
        If ProcessExists("AcroRd32.exe") Then ProcessClose("AcroRd32.exe")
    Until Not ProcessExists("AcroRd32.exe")
    Do
        If ProcessExists("SWViewer.exe") Then ProcessClose("SWViewer.exe")
    Until Not ProcessExists("SWViewer.exe")
    Do
        If ProcessExists("WORDVIEW.exe") Then ProcessClose("WORDVIEW.exe")
    Until Not ProcessExists("WORDVIEW.exe")
    Do
        If ProcessExists("XLVIEW.exe") Then ProcessClose("XLVIEW.exe")
    Until Not ProcessExists("XLVIEW.exe")
    Do
        If WinExists("Bill of Materials") Then WinClose("Bill of Materials")
    Until Not WinExists("Bill of Materials")

    Dim $oMyError

; Initializes COM handler
    $oMyError = ObjEvent("AutoIt.Error","MyErrFunc")

    $SOado = ObjCreate( "ADODB.Connection" )    ; Create a COM ADODB Object

    With $SOado
        .ConnectionString =("DELETED FOR PRIVACY")
        .Open
    EndWith

    $SOrs = ObjCreate( "ADODB.RecordSet" )    ; Create a Record Set to handle SQL Records

    With $SOrs
        .ActiveConnection = $SOado
        ;~ ".Source" send the SQL query to the DB. This one grabs the Part Number based on the shop order number.
        .Source = "SQL QUERY"
        .Open
    EndWith

    $sPN = $SOrs.Fields(0).Value
    $SOrs.Close()
    $SOrs = 0
    $SOado.Close()
    $SOado = 0
    Return $sPN

EndFunc   ;==>_NewSO

Func _BOM($PN)

    Dim $oMyError

; Initializes COM handler
    $oMyError = ObjEvent("AutoIt.Error","MyErrFunc")

    $BOMado = ObjCreate( "ADODB.Connection" )    ; Create a COM ADODB Object

    With $BOMado
        .ConnectionString =("Deleted for privacy")
        .Open
    EndWith

    $BOMrs = ObjCreate( "ADODB.RecordSet" )    ; Create a Record Set to handle SQL Records

    With $BOMrs
        .ActiveConnection = $BOMado
        ;~ ".Source" send the SQL query to the DB. This one grabs the BoM based on the shop order number.
        .Source = " SQL QUERY "
        .Open
    EndWith

    Local $aBOM[1][10]

    $j=0
    $i=0

    While not $BOMrs.EOF
        ReDim $aBOM[$j+1][10]
        For $i = 0 To $BOMrs.Fields.Count - 1
            $aBOM[$j][$i] = $BOMrs.Fields( $i ).Value
        Next
        $BOMrs.MoveNext     ; Go to the next record
        $j = $j+1

    WEnd

    $BOMrs.Close()
    $BOMrs = 0
    $BOMado.Close()
    $BOMado = 0

    $iRows = UBound($aBOM, 1)

    $r = $iRows-1

    For $r = $iRows - 1 to 1 Step -1
        $s = $r - 1
        If $aBOM[$r][0] = $aBOM[$s][0] Then
            $aBOM[$r][0] = Null
            $aBOM[$r][1] = Null
            $aBOM[$r][2] = Null
            $aBOM[$r][3] = Null
            $aBOM[$r][4] = Null
        EndIf
    Next

;~      ; Create GUI
    $BOMgui = GUICreate("Bill of Materials",@DesktopWidth,@DesktopHeight,-1,-1,$WS_MAXIMIZEBOX)
    GUISetState(@SW_SHOW)
    WinSetState($BOMgui, "", @SW_MAXIMIZE)
    $idListview = GUICtrlCreateListView("", 2, 2, @DesktopWidth-4, @DesktopHeight-58)


    ; Add columns
    _GUICtrlListView_AddColumn($idListview, "DRW#", 40)
    _GUICtrlListView_AddColumn($idListview, "Component PN", 80)
    _GUICtrlListView_AddColumn($idListview, "Description", 500)
    _GUICtrlListView_AddColumn($idListview, "Qty.", 40)
    _GUICtrlListView_AddColumn($idListview, "UoM", 40)
    _GUICtrlListView_AddColumn($idListview, "Sub DRW#", 40)
    _GUICtrlListView_AddColumn($idListview, "Sub Component PN", 80)
    _GUICtrlListView_AddColumn($idListview, "Sub Description", 500)
    _GUICtrlListView_AddColumn($idListview, "Sub Qty.", 40)
    _GUICtrlListView_AddColumn($idListview, "Sub UoM", 40)

    _GUICtrlListView_SetItemCount($idListview, $iRows)

    _GUICtrlListView_AddArray($idListview, $aBOM)

    GUISetState(@SW_SHOW, $BOMgui)

    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                Exit
        EndSwitch
    WEnd

;~  _ArrayDisplay($aBOM, "Bill of Materials - " & $PN,"",96,"","DRW#|Comp. PN|Description|Qty.|UoM|Sub DRW#|Sub Comp PN|Sub Description|Sub Qty.|Sub UoM")
EndFunc   ;==>_BOM

Func _OpenDoc($PN,$AC) ;~~ This function will open a connected object based on the Association Category specified ~~

    $Adobe1 = UBound(Winlist("[REGEXPTITLE:(?i)(.*Adobe Reader.*)]"), 1) - 1
    $XLVW1 = UBound(Winlist("[REGEXPTITLE:(?i)(.*Microsoft Excel Viewer.*)]"), 1) - 1
    $WDVW1 = UBound(Winlist("[REGEXPTITLE:(?i)(.*Microsoft Word Viewer.*)]"), 1) - 1

    Dim $oMyError

; Initializes COM handler
    $oMyError = ObjEvent("AutoIt.Error","MyErrFunc")

    $DOCado = ObjCreate( "ADODB.Connection" )    ; Create a COM ADODB Object

    With $DOCado
        .ConnectionString =("DELETED FOR PRIVACY")
        .Open
    EndWith

    $DOCrs = ObjCreate( "ADODB.RecordSet" )    ; Create a Record Set to handle SQL Records

    With $DOCrs
        .ActiveConnection = $DOCado
        ;~ ".Source" send the SQL query to the DB. This one grabs the BoM based on the shop order number.
        .Source = "SQL QUERY"
        .Open
    EndWith

    If Not $DOCrs.EOF Then

    Local $aDOC[2]
    $aDOC[0] = $DOCrs.Fields( 0 ).Value
    $aDOC[1] = $DOCrs.Fields( 1 ).Value
    $sDOC = _ArrayToString($aDOC,"",0,1)
    ShellExecute($sDOC)

    EndIf

    $DOCrs.Close()
    $DOCrs = 0
    $DOCado.Close()
    $DOCado = 0

    $Adobe2 = UBound(Winlist("[REGEXPTITLE:(?i)(.*Adobe Reader.*)]"), 1) - 1
    $XLVW2 = UBound(Winlist("[REGEXPTITLE:(?i)(.*Microsoft Excel Viewer.*)]"), 1) - 1
    $WDVW2 = UBound(Winlist("[REGEXPTITLE:(?i)(.*Microsoft Word Viewer.*)]"), 1) - 1

    If $Adobe2 > $Adobe1 Then Call("_Adobe")
    If $XLVW2 > $XLVW1 Then Call("_XLVW")
    If $WDVW2 > $WDVW1 Then Call("_WDVW")

EndFunc   ;==>_OpenDoc

 

Edited by alexm963

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

I've tried having the first function return the GUI with the array as a listview and then display it in the main script, but it still closes as soon as the script gets to the next function. Any ideas?

Edited by alexm963

Share this post


Link to post
Share on other sites

To keep the gui alive you need a While loop... and you're trapped
Either manage to use other funcs from inside this While loop, or separate the processes as Larsj suggested  :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now