Jump to content
FMS

array in array

Recommended Posts

RTFC

One thing you're doing wrong is calling CloneMatrix with 2nd param $copydata=False (so the new matrix is empty), and then immediately using that empty result in a multiplication. Otherwise, provided the adjacent dimensions match (that is, if A.cols()==B.transpose().rows(), so if A.cols()==B.cols()),

_Eigen_Multiply_ABt

should produce valid output. The default setting of $copydata is True, because most of the time when you clone, you'll want the same content as well as the same shape.

Edited by RTFC

Share this post


Link to post
Share on other sites
kylomas

RTFC, FMS, jchd, 

Thank you for the insight and links!

Kylomas


Forum Rules         Procedure for posting code

"I like pigs.  Dogs look up to us.  Cats look down on us.  Pigs treat us as equals."

- Sir Winston Churchill

Share this post


Link to post
Share on other sites
FMS

Is there by any chanse an function to put all row's of a matrix inside a vector's cel in E4A?
like (code) from (image) :

Local $temp = 0

For $k = 0 To UBound($M_bias_h2,1) -1
    For $j = 0 To UBound($M_grad_h2,2) -1
        $M_bias_h2[$k] += $M_grad_h2[$k][$j]
    Next
Next

I've tried a lot but couldn't get any good results :(

 

 

Untitled.png


as finishing touch god created the dutch

Share this post


Link to post
Share on other sites
RTFC

_Eigen_MatrixSpecs_Rowwise_Single ( $matA, $specID) with specID=2 (sum) does what you want.

NB not clear from your example whether vector M_bias_h2 is empty (zero) before, but if not, you'd collect the result in a temporary vector which you then add to M_bias_h2 with CwiseBinaryOp.

Edited by RTFC
typo

Share this post


Link to post
Share on other sites
junkew

You can get your array back and forth into excel in 1 call directly no need to do it per cell (which is terribly slow)
Example below demonstrates the concept

$oExcel=objcreate("excel.application")
$oExcel.visible=1

$oWB=$oExcel.workbooks.add()
$oWS=$oWB.worksheets.add()

;~ putting it In
Local $aArray[2][2]
$aArray[0][0] = "A1"
$aArray[1][0] = "A2"
$aArray[0][1] = "B1"
$aArray[1][1] = "B2" 

$oWS.Range("A1:B2").value=$aArray

;~ getting it out, see you get a different range back including empty cells
$oVarArr=$oWS.Range("A1:C2").value

for $i=0 to ubound($oVarArr,1)-1
    for $j=0 to ubound($oVarArr,2)-1
        consolewrite("<" &  $i & ";" & $j & ";" & $oVarArr[$i][$j] & ">")
    Next
Next

 

Share this post


Link to post
Share on other sites
RTFC

@junkew: Come again?:blink: Maybe you misunderstood that last question (about E4A, not Excel), or answered in the wrong thread? Or is this a glitch in the matrix?;)

Doing neural nets in Excel would be like building a fusion reactor with Lego bricks.:D

Share this post


Link to post
Share on other sites
junkew

yep, was reading E4A as xls (>ლ)

yep, like also lego anyway so also excel is an option (i would switch for neural programming more to a compiled language anyway)

https://quantmacro.wordpress.com/2015/08/13/artificial-neural-network-with-backpropagation-training-in-vba/

The E4A library looks nice to do matrix calculations 

If the OP is still on arrays look into this thread

 

 

Share this post


Link to post
Share on other sites
RTFC

I love Lego too.;)

37 minutes ago, junkew said:

a compiled language

Yeah, that's (part of) why E4A uses a compiled C++ dll.:) A major limitation of AutoIt arrays (regardless of access time) is the meagre size limit, whereas E4A matrices can be any size that fits into virtual memory (in x64 mode, that is, otherwise only <2GB).

Share this post


Link to post
Share on other sites
FMS
Quote

Doing neural nets in Excel would be like building a fusion reactor with Lego bricks.  :D

Also mine riaction in a simelar line :lol:

I'm more in to it too understand the math/code behind the AI.

Also whit E4A the code looks more simpler i must say and mush better performanse than only "array-based"

A big plus B)

Is there by anyway a posibility to find the id of the higest in a matrix?
e.g. -> largest output in the "output layer -vector" so i can store it?

At this point I'm try to do something like this in vectors :

#include <Array.au3> ; also for multiping

;~ _Eigen_StartUp()

Global $aArray[10][1]
Global $bArray[10][1]


For $i = 0 to 9
   $aArray[$i][0] = 0
   $bArray[$i][0] = 0
Next

$aArray[Random(1 , UBound($aArray,1) - 1 , 1)][0] = 1
$bArray[Random(1 , UBound($bArray,1) - 1 , 1)][0] = 1

Global $correct = False
Global $guessed_id = -1
Global $target_id = -1

For $i = 0 to 9
   If $aArray[$i][0] = 1 Then $guessed_id = $i
   If $bArray[$i][0] = 1 Then $target_id = $i
   If $aArray[$i][0] = 1 And $bArray[$i][0] = 0 Then
      $correct = True
   EndIf
Next


_ArrayDisplay ($aArray)
_ArrayDisplay ($bArray)
MsgBox($MB_SYSTEMMODAL, "Title", "$guessed_id -> " & $guessed_id & " $target_id " & $target_id , 10)
If $correct Then MsgBox($MB_SYSTEMMODAL, "Title", "guessed -> correct!!"  , 10)

ofcource the outputs aren't 0 and 1 and i use _ArraySort($outputs_os, 1, 1, 0, 1) for this
($outputs_os[$i][2] is an array whit and id and a output of -1 to 1)

Edited by FMS

as finishing touch god created the dutch

Share this post


Link to post
Share on other sites
RTFC

Like your earlier question, you're taking a matrix to extract something dimensionally smaller from it, e.g., a vector (rowwise sum, or maybe a list of the frequencies of the unique values in the matrix) or in this case, a scalar (the maximum value). These are examples of so-called matrix reduction. In the E4A Help, go to the chapter heading "Reduction" (not the actual functions underneath it). At the bottom of the page you'll find a table with all scalar specs you can extract (sum, product, mean, and so forth). There you'll also find minimum and maximum value, plus their row/col coordinates. Note that not all matrix part function variants support all specs. But if it's just the max value you're after, you don't need to sort the matrix first (for sorting, see functions under the heading "Transformation").

All clear?:)

Share this post


Link to post
Share on other sites
RTFC

@FMS:NB instead of using CwiseScalarOp with params "*",-1 (in the sigmoid function), using CwiseUnaryOp with param "-" (minus) should be slightly faster.

Furthermore, if you're serious about image recognition, your programme would likely benefit from a PCA preprocessing pass instead of feeding it raw image data. This is for example used in facial recognition software, google "eigenface" to learn more. Just a thought. Check out E4A's PCA tutorial if you're interested.

Edited by RTFC

Share this post


Link to post
Share on other sites
FMS

Nice,

checked , tested and implemented :) (thanks @RTFC )

$quessed_id = _Eigen_MatrixSpecs_Single ( $M_outputs_o, 14 )
$quessed_value = _Eigen_MatrixSpecs_Single ( $M_outputs_o, 11 )
$target_id = _Eigen_MatrixSpecs_Single ( $M_target_o, 14 )

MsgBox($MB_SYSTEMMODAL, "Title", "guessed -> " & $quessed_id & @CRLF & "value -> " & $quessed_value  , 10)
MsgBox($MB_SYSTEMMODAL, "Title", "target -> " & $target_id  , 10)

also whit :

_Eigen_CwiseUnaryOp_InPlace ( $M_outputs_h1, "-" )
_Eigen_CwiseUnaryOp_InPlace($M_outputs_h1,"exp")
_Eigen_CwiseScalarOp_InPlace($M_outputs_h1,"+",1)
_Eigen_CwiseUnaryOp_InPlace($M_outputs_h1,"inverse")
Quote

Check out E4A's PCA tutorial if you're interested.

I've looked into it but I'm not shure what u mean I must say :) and also how I can benefit from " Principal Components Analysis " ? (maybe i don't undestand the math ;) )
I'm inplementing the raw data into array's and afther "normelizing" it I put it in a Matrix whit :

Func normelize_input()
   Local $input_min = 0
   Local $input_max = 255
   For $i = 0 To UBound($A_inputs,1) -1
      $A_Ninputs[$i] = round(($A_inputs[$i] - $input_min) / ($input_max - $input_min),4)
   Next
   $M_Ninputs = _Eigen_CreateMatrix_FromArray ( $A_Ninputs, True )
EndFunc

I'm not realy aiming for "image recognition" , at first I want to make the math working .
The files (t10k-images.idx3-ubyte / t10k-labels.idx1-ubyte) are just files I found to test the math.
 

 

Edited by FMS

as finishing touch god created the dutch

Share this post


Link to post
Share on other sites
RTFC

The advantage of a precursor PCA pass is that your inputs will consist of uncorrelated contributions to data variability, which means any algorithm dealing with distinguishing between different inputs (to produce some desired different behaviours/responses) does not have to deal with covariant inputs, making the decision-making process much easier (because it does not have to disentangle raw parameters that mutually affect one another in some way). Facial recognition was just an example; in the linked page, you cansee lots of different pics of the same face; PCA can reduce each one to their common denominator,i.e., the basic face underlying all different expressions and lighting conditions. If you have lots of different people as inputs, PCA can define the common face underlying all, then define each person as how it departs from the common face. (Those two approaches can also becombined).

But if you're focussed on getting the math working, just forget about PCA for now (but remember it for later on, maybe). Think of it as a noise filter for the (artificial) mind.

Share this post


Link to post
Share on other sites
FMS

Thanks for the info @RTFC , I'll look into it.

Seems intresting but I'm not shure how to implement this :(

Do you have an idea how to do the folowing?
I hope the code say's enough :)

I tried multiple functions but couldn't get it to work (most of it I get the error message complaining about mismatch in dimensions)

I'm sure that what I'm trying to do is a function in E4A but couldn't find it.
(still a little unsure about the naming but got the math down I think :D )

#include "Eigen4AutoIt.au3"
#include <Array.au3> 

_Eigen_StartUp()
Local $aArray[3][2] = [[1, 2], [3, 4], [5, 6]]
Local $bArray[3][1] = [[1], [2], [3]]
Local $cArray[3][1] = [[0], [0], [0]]
Global $matA
Global $matAT
Global $matB
Global $matC

;$cArray[0] = (($aArray[0][0] * $bArray[0]) + ($aArray[0][1] * $bArray[1] ) + ...)
;$cArray[1] = (($aArray[1][0] * $bArray[0]) + ($aArray[1][1] * $bArray[1] ) + ...)
;$cArray[2] = (($aArray[2][0] * $bArray[0]) + ($aArray[2][1] * $bArray[1] ) + ...)
;....

$matA = _Eigen_CreateMatrix_FromArray ( $aArray, True )
$matAT = _Eigen_Transpose ( $matA )
$matB = _Eigen_CreateMatrix_FromArray ( $bArray, True )
$matC = _Eigen_CreateMatrix_FromArray ( $cArray, True )

$matC = _Eigen_Multiply_AtB  ($matA,$matB)

_MatrixDisplay ( $matA, "$matA" )
_MatrixDisplay ( $matAT, "$matAT" )
_MatrixDisplay ( $matB, "$matB" )
_MatrixDisplay ( $matC, "$matC" )

_Eigen_CleanUp()

 


as finishing touch god created the dutch

Share this post


Link to post
Share on other sites
RTFC

Oh dear.:o Where to begin? :think: Some clean E4A code maybe.:idea:

#include "..\Eigen4AutoIt.au3"

_Eigen_StartUp()

Global $matA = _Eigen_CreateMatrix_LinSpaced_RowMajor(3,2,1,6)
_MatrixDisplay ( $matA, "$matA" )

Global $matB = _Eigen_CreateMatrix_LinSpaced_ColMajor(3,1,1,3)
_MatrixDisplay ( $matB, "$matB" )

Global $matC = _Eigen_Multiply_AtB ( $matA, $matB )
_MatrixDisplay ( $matC, "$matC" )

_Eigen_CleanUp()

Some pointers:

  • #include <Array.au3> is superfluous, because E4A already includes it.
  • use Linspaced matrix creation functions to fill a matrix with regularly-spaced values (rows, cols, first value, last value)
  • it's not wrong to predeclare all globals at the top of the script, but I wouldn't use 4 lines for 4 globals; in such a small test script, I'd declare the globals as they are created/filled with values
  • you're using an internal-transpose function (little "t" in function name: _AtB); that means you don't (need to) create a separate transposed matrix A; the function instead takes the original A, and accesses it transposed. So no need to create $matAT at all.
  • results container C is automatically created for you (unless you explicitly presupply it in the multiply call) with the correct dimensions. From your array definition, you seem to expect a matrix multiplication of [2,3] . [3,1] to produce a [3,1]- shaped output matrix. That's plain wrong. The multiplication itself is valid because the adjacent ("inner") dimensions of At and B are the same (3): [2,3] . [3,1]. The final result accumulates in a container defined by the outer dimensions, so [2,1], not [3,1], viz.: [2,3].[3,1] Maybe review the matrix multiplication chapter introduction in the Help file?
  • If instead you wish to perform a cell-wise vector-multiply per row or column, look into _Eigen_CwiseBinaryOp_Colwise/Rowwise. Note that your vector B needs to have the right shape, that is, being either a Colvector [N,1]  or a RowVector [1,N], with N matching the corresponding dimension in matrix A. You already know how to obtain the Rowwise/Colwise sum (see MatrixSpecs_Row/Colwise_Single)
  • If you're unsure how some function you're trying out is supposed to work, start by copying the example script in the E4A Help, run it (to see how it works), then edit it to suit your needs.

Hope it helps.;)

Edited by RTFC
typos

Share this post


Link to post
Share on other sites
FMS

O, sorry @RTFC I see now that I left some testing code inside the test-script :>

The question i tried to ask was how to calculate :

$vectorB[0] = (($matrix[0][0]*$vectorA[0])+($matrix[1][0]*$vectorA[1])+($matrix[2][0]*$vectorA[2])+...)
$vectorB[1] = (($matrix[0][1]*$vectorA[0])+($matrix[1][1]*$vectorA[1])+($matrix[2][1]*$vectorA[2])+...)
$vectorB[2] = (($matrix[0][2]*$vectorA[0])+($matrix[1][2]*$vectorA[1])+($matrix[2][2]*$vectorA[2])+...)
...

sorry for the confusion.

Could you shine a light on the folowing?
I'm not shure how to release the matricies and thought all the used matricies where released in the code below.
Also is there a "best-habit" in making and releasing matricies in loops?

#include "Eigen4AutoIt.au3"
Global $mat[3][3]

_Eigen_StartUp()

   For $x = 0 To 2
      $mat[$x][0] = _Eigen_CreateMatrix (3,2)
      $mat[$x][1] = _Eigen_CreateMatrix (3,1)
      $mat[$x][2] = _Eigen_CreateMatrix (2,1)
   Next
;~ _Eigen_Show_MatrixList()
feed()


_Eigen_Show_MatrixList()
   For $x = 0 To 2
      _Eigen_ReleaseMatrix ( $mat[$x][0] )
      _Eigen_ReleaseMatrix ( $mat[$x][1] )
      _Eigen_ReleaseMatrix ( $mat[$x][2] )
   Next
_Eigen_Show_MatrixList()

_Eigen_CleanUp()

Func feed()
      _Eigen_SetListMarker()
   For $x = 0 To 2
;~    _Eigen_SetListMarker()
      $mat[$x][0] = _Eigen_SetLinSpaced_RowMajor ($mat[$x][0],1,6)
;~    _MatrixDisplay ( $mat[$x][0], "$mat[$x][0]" )

      $mat[$x][1] = _Eigen_SetLinSpaced_RowMajor ($mat[$x][1],1,3)
;~    _MatrixDisplay ( $mat[$x][1], "$mat[$x][1]" )

      $mat[$x][2] = _Eigen_Multiply_AtB ( $mat[$x][0], $mat[$x][1] )
;~    _MatrixDisplay ( $mat[$x][2], "$mat[$x][2]" )
;~    _Eigen_ReleaseFromMarker()
;~    _Eigen_ReleaseMatrix ( $mat[$x][0] )
;~    _Eigen_ReleaseMatrix ( $mat[$x][1] )
;~    _Eigen_ReleaseMatrix ( $mat[$x][2] )
   Next
      _Eigen_ReleaseFromMarker()

;~    For $x = 0 To 2
;~    _Eigen_ReleaseMatrix ( $mat[$x][0] )
;~    _Eigen_ReleaseMatrix ( $mat[$x][1] )
;~    _Eigen_ReleaseMatrix ( $mat[$x][2] )
;~    Next

EndFunc


 


as finishing touch god created the dutch

Share this post


Link to post
Share on other sites
RTFC

Although E4A has various built-in safeguards to minimise the risk of memory leaks upon (unexpected) Exits, it's good practice to release matrices as soon as you no longer need them. What you do in your code snippets looks fine,^_^ using SetListMarker before creating some work spaces, and using ReleaseFromMarker immediately afterwards to clear them (I'm just a bit confused by storing these IDs in a 2D array, but that's up to you). Note that a variant of this function, ReleaseFromMarker_Except(), allows you to exclude up to 10 specified matrix IDs from that release action (e.g., to keep a final result while discarding all temporary buffers). Of course, releasing matrix allocations individually with _Eigen_ReleaseMatrix(<matID>) is also fine. Note that calling _Eigen_CleanUp() at the end of a session will automatically release all remaining used entries in the $matrixList for you. You can do this yourself at other times by calling _Eigen_ReleaseMatrix_All(). To review these functions, study Help sections "Work Environment" and "Matrix Management."

Since matrix IDs are sequentially assigned and slots in the list are not re-used during a session, you can also use _Eigen_ReleaseFromIndex_ToIndex to clear a specific block of IDs in a single call. If you need more control, remember that matrix IDs are just the index numbers of the entries in the $MatrixList array. You can use internal function _Eigen_GetNewMatrixID() to figure out ahead of time what the next free ID to be assigned to a newly created matrix will be.

The one thing you should NOT do is edit the $matrixList array directly yourself (with _ArrayDelete, _ArrayAdd, etc), as E4A needs to keep track of how much space to dynamically allocate to keep all the matrix admin correct. This is especially important in x64 (64-bit mode), where part of this admin is off-loaded to my HighMem UDF (which enables matrices of unlimited size (>2GB, up to whatever fits into your virtual memory (which can greatly exceed your physical RAM) that can be accessed simultaneously by multiple processes, which can hugely speed up calculations; but that's another story). So whatever you do, please use only the provided functions to manipulate the list. Speaking of x64, if you find that you're constantly running out of memory due to allocating too many large matrices, switch to x64 mode (if you have x64 hardware running a 64-bit OS, that is) by adding directive "#AutoIt3Wrapper_UseX64=Y" at the top of your script. This may also speed up some computations a bit.:drool:

Edited by RTFC

Share this post


Link to post
Share on other sites
RTFC
1 hour ago, FMS said:

question i tried to ask

See the penultimate point in my previous answer:

If you wish to perform a cell-wise vector-multiply per row or column, look into _Eigen_CwiseBinaryOp_Colwise/Rowwise. Note that your vector B needs to have the right shape, that is, being either a Colvector [N,1]  or a RowVector [1,N], with N matching the corresponding dimension in matrix A. You already know how to obtain the Rowwise/Colwise sum (see MatrixSpecs_Row/Colwise_Single).

Edited by RTFC

Share this post


Link to post
Share on other sites
FMS

I must say, now I'm getting to the end of a working "feed forward" and "back propagration" E4A is a usefull tool. 
Its a little work on getting to know all the correct functions for the matricies and vectors you have.
(naming wise I'm not getting the hang of it but know how it works :D )

On 9-5-2018 at 3:23 PM, RTFC said:

(I'm just a bit confused by storing these IDs in a 2D array, but that's up to you).

@RTFC - I'm using at this point 2d array's because in the futher I want to make 1 network (matricies id's ) in a row of the 2d array (weights  , inputs , outputs etc.)

At this point I'm looking at the floor and ciel functions.
I'm not shure if I'm having the right function for this but I want to set al the intigers in a matrix (or a vector) to 0 if it's below 0.
Or 1 if it's higer then 1.
(in the futher I think I want to use other max and min digits)

Is this possible in E4A ? (I think it does but couldn't find the right function)

 


as finishing touch god created the dutch

Share this post


Link to post
Share on other sites
RTFC

The perfect functions for bit-masking would be _Eigen_ConditMask/_Eigen_ConditMask_InPlace. However, there's a serious issue in the way Eigen implements the underlying .select() operator that I've only just fixed yesterday (well, circumvented, more like) for the next release (v4.3); ConditMask in version 4.2 should work, but ConditMask_InPlace in v4.2 is unstable (it will likely crash, or hang). So until 4.3 is ready for release, you'd best use a slightly more cumbersome double call of conditional replace, using _Eigen_ConditScalarOp/_InPlace (with "replace" operator).

Edit: actually, if you wish to retain true values in the [0,1] interval, then you shouldn't be using bit-masking, so stick with ConditScalarOp/_InPlace.

Edited by RTFC

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

  • Similar Content

    • Burgs
      By Burgs
      Greetings,
        I seem to be having a problem trying to insert values into an array in excess of the size of the array (its Ubound value).  I thought the command would simply 'ReDim' the array in order to add another value...however that does not seem to be happening.  My code is as below:
       
      ;**SET DYNAMIC ARRAY DIMENSIONS... $vValue = Int($_STRUCTURE_LEVEL - 1) ;seek the '$_HIERARCHY' level that is one 'previous' to the 'current' value...! $iStart = 0 ;set to begin search from element "0" in array... Do $_Files_Located = _Arraysearch($_HIERARCHY, $vValue, $iStart) if Int($_Files_Located) <> -1 Then $iEnd = 1 For $_RIGGING = 0 to Ubound($_LINE_DETAIL3) - 1 _ArrayInsert($_STRUCTURES, $_Files_Located + $iEnd, String($_LINE_DETAIL3[$_RIGGING])) _ArrayInsert($_HIERARCHY, $_Files_Located + $iEnd, Int($_STRUCTURE_LEVEL)) _ArrayInsert($_INFERIOR_TMPLS, $_Files_Located + $iEnd, Int(-1)) $iEnd += 1 ;increment EACH ITERATION... Next ;Next $_RIGGING EndIf ;'$_Files_Located' NOT "-1"...value for previous '$_STRUCTURE_LEVEL' ;was located in '$_HIERARCHY' array... $iStart += (Ubound($_LINE_DETAIL3) + 1) ;increment the offset index element position to begin the next search... ;"+ 1" to INCLUDE the 'parent' ('searched') UNIT...! Until $_Files_Located == -1 ;end loop when previous '$_STRUCTURE_LEVEL' is NOT found in '$_HIERARCHY' array... ;**  
        This code routine works perfectly fine except when the 'searched' value ($_Files_Located) happens to be the final element position in the searched array...how can I modify this routine so that the final additions at the end of the array(s) are made?  I thank in advance for any replies. 
       
    • DarkFingers1337
      By DarkFingers1337
      Hey,
      what is more efficient, using multiple arrays or one multidimensional array?
       
      ; Hamster data structure using multiple arrays Global $HamsterCount = 6 Global $HamsterX[$HamsterCount] Global $HamsterY[$HamsterCount] ;giving each hamster an x and y position For $i=0 To $HamsterCount-1 $HamsterX[$i] = 0 $HamsterY[$i] = 0 Next ; The same hamster data structure using one multidimensional array Global $HAMSTER_COUNT = 6 Global Enum $HAMSTER_X, _ $HAMSTER_Y, _ $HAMSTER_MAX Global $Hamsters[$HAMSTER_COUNT][$HAMSTER_MAX] ;giving each hamster an x and y position For $i=0 To $HAMSTER_COUNT-1 $Hamsters[$i][$HAMSTER_X] = 0 $Hamsters[$i][$HAMSTER_Y] = 0 Next  
    • Skysnake
      By Skysnake
      I know how JSON works. However JSON data is typically received from web based servers. 
       
      My question is:
      Has anyone considered to use, or currently actively using JSON as an internal data container? 
      Internal here as in an ordinary AutoIt data type, generated, populated and manipulated within an AutoIt script, without any external data sources. 
      The JSON and BinaryCall UDFs work well and appear the de facto defaults. Are there any thoughts on using JSON for internal variable values instead of the typical array? 
      Also, there can be situations where such a JSON collection contains an array and it will have to be parsed using typical array functions. 
      Currently I am working on a small project where I have to keep and use various identifiers from different sources. There are several ideas in this regard, some involving SQL child tables and arrays stored with keys (maps), which lead me to think that JSON may be a more suitable data container. It readily shrinks and stretches, allowing for dynamic data growth.  JSONs ability to add new repeating data groups on the fly makes it particularly powerful and appealing. 
      Ideas and suggestions welcome
      Skysnake
    • XinYoung
      By XinYoung
      Hello all! I hope everyone is enjoying their holiday festivities. 
      I'm working on a script that involves copying a string of text from an Excel workbook and searching for it in a particular website's search tool. If a result is found, it will do something. If not, it will do something else.
      So far, it can successfully execute the search -- and then it shows me the results in an array.
      Screenshot of the successful search:

      The search results in an array:

       
      Here's the code (sorry for all my comments):
      ;~ All the functions this app performs require the external files listed here. So, theyre "included". #include <ButtonConstants.au3> #include <EditConstants.au3> #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3> #include <WinAPIFiles.au3> #include <Array.au3> #include <File.au3> #include <Excel.au3> #include <DateTimeConstants.au3> #include <MsgBoxConstants.au3> #include <WinAPIShellEx.au3> #include <Date.au3> #include <ComboConstants.au3> #include <Misc.au3> #include <WinAPIProc.au3> #include <WinAPISys.au3> #include <WinAPIConstants.au3> #include <Crypt.au3> #include <ColorConstants.au3> #include <guimenu.au3> #include <IE.au3> ;~ Kill all functions and close the app at anytime by pressing F4. HotKeySet("{F4}", "_Exit") ;~ Keep track whether or not a file is selected. When the program first opens, a file is currently not selected. Global $FileChosen = 0 ;~ The app must remember certain strings of text: ;~ 1. Login page Global $urlBBLogin = "website.com" ;~ 2. Credentials Global $bbUsername = "USER" Global $bbPassword = "PW" ;~ 3. Search page Global $urlBBCourseSearch = "website.com/search" ;~ When you launch the app, the UI gets built and is displayed to the user in the center of the screen. the "Function" buttons are disabled until a file is chosen. $MasterUI = GUICreate("Master Re-Creator", 469, 145, -1, -1) $Label1 = GUICtrlCreateLabel("Choose the Excel file", 8, 8, 103, 17) $Select = GUICtrlCreateButton("Select File", 16, 32, 75, 25) $FileName = GUICtrlCreateLabel("[No File Selected]", 104, 40, 88, 17) $Group1 = GUICtrlCreateGroup("Functions", 8, 72, 449, 65) $CheckCourse = GUICtrlCreateButton("Check Courses Exist", 24, 96, 123, 25) GUICtrlSetState(-1, $GUI_DISABLE) $DeleteCourse = GUICtrlCreateButton("Delete Courses", 168, 96, 123, 25) GUICtrlSetState(-1, $GUI_DISABLE) $CopyCourse = GUICtrlCreateButton("Copy Courses", 312, 96, 123, 25) GUICtrlSetState(-1, $GUI_DISABLE) GUICtrlCreateGroup("", -99, -99, 1, 1) GUISetState(@SW_SHOW) ;~ While the UI is open, it listens for triggers (in this case, button presses). While 1 $UI = GUIGetMsg() Select ;~ If the app is closed, the _Exit() function is performed (same function the F4 hotkey calls). Case $UI = $GUI_EVENT_CLOSE _Exit() ;~ The user has clicked the "Select File" button, the _LocateGetFileName() function is performed. Go there. Case $UI = $Select _LocateGetFileName() ;~ The user has clicked the "Check Courses Exist" button. Case $UI = $CheckCourse _CheckCourses() ;~ Other buttons are not ready EndSelect WEnd ;~ The user clicked the "Select File" button. This function will execute now. Func _LocateGetFileName() ;~ Prepare the app to take note of the details of a file. Local $sDrive = "", $sDir = "", $sFileName = "", $sExtension = "" ;~ Open a File Explorer to allow the user to select a file. Only Excel files are allowed to be chosen. Global $ChosenFileName = FileOpenDialog("Locate File", @DesktopDir, "Excel Files (*.xlsx)|Excel Macro Files (*.xlsm)", BitOR(1, 2), "") If @error Then Return 0 EndIf ;~ When an Excel file is selected, remember of the files location (path), file name, and file extension. $aPathSplit = _PathSplit($ChosenFileName, $sDrive, $sDir, $sFileName, $sExtension) ;~ Show me what file I selected in a Message Box. MsgBox(0, "Selected File", $sFileName) ;~ Display the chosen file name in the UI label (previously [No File Selected]) and make it green. GUICtrlSetData($FileName, "") $FileName = GUICtrlCreateLabel($sFileName, 104, 40) $FileName = GUICtrlSetColor($FileName, 0x32CD32) ;~ A file is now selected. The "Function" buttons are now enabled. Global $FileChosen = 1 GUICtrlSetState($CheckCourse, $GUI_ENABLE) GUICtrlSetState($DeleteCourse, $GUI_ENABLE) GUICtrlSetState($CopyCourse, $GUI_ENABLE) EndFunc ;==>_LocateGetFileName ;~ The user clicked the "Check Courses" button. This function will execute now. Func _CheckCourses() ;~ Disable the "Function" buttons again to prevent multiple processes. GUICtrlSetState($CheckCourse, $GUI_DISABLE) GUICtrlSetState($DeleteCourse, $GUI_DISABLE) GUICtrlSetState($CopyCourse, $GUI_DISABLE) ;~ Open a IE window and navigate to the login page. Global $oIE = _IECreate($urlBBLogin) ;~ Recognize the form on this page (login input boxes). Local $oForm = _IEFormGetObjByName($oIE, "login") Local $oTextLogin = _IEFormElementGetObjByName($oForm, "user_id") Local $oTextPass = _IEFormElementGetObjByName($oForm, "password") ;~ Enter the Automation user credentials into the form. _IEFormElementSetValue($oTextLogin, $bbUsername) _IEFormElementSetValue($oTextPass, $bbPassword) ;~ Click the Login button. _IEFormSubmit($oForm) ;~ Now that were logged in, navigate to the course search page. _IENavigate($oIE, $urlBBCourseSearch) ;~ Change the search criteria to "Course ID" _bbCourseSearchCategoryChange("Course ID") ;~ Open the selected Excel file Local $oAppl = _Excel_Open() Local $oWorkbook = _Excel_BookOpen($oAppl, $ChosenFileName, Default, Default, True) ;~ Copy just whats in cell A1 (for now) _Excel_RangeCopyPaste($oWorkbook.Worksheets(1), "A1") Global $WhatsCopied = ClipGet() ;~ Paste whats copied into the search text box and click submit Local $oForm = _IEGetObjByName($oIE, "courseManagerFormSearch") Local $oSearchString = _IEFormElementGetObjByName($oForm, "courseInfoSearchText") _IEFormElementSetValue($oSearchString, $WhatsCopied) _IEFormSubmit($oForm) ;~ Lets see what we got from the search Local $oBBTable = _IETableGetCollection($oIE, 2) Local $aBBTableData = _IETableWriteToArray($oBBTable) _ArrayDisplay($aBBTableData) EndFunc ;==>_CheckCourses ;~ This function allows changing the search criteria. Func _bbCourseSearchCategoryChange($sCategoryToSearch) Local $aSearchCategory[6] = ["Course ID", "Course Name", "Description", "Instructor", "Data Source Key", "Term"] Local $oForm = _IEGetObjByName($oIE, "courseManagerFormSearch") Local $oSearchCategory = _IEGetObjByName($oForm, "courseInfoSearchKeyString") _IEAction($oSearchCategory, "focus") _IEFormElementOptionSelect($oSearchCategory, $aSearchCategory[$sCategoryToSearch], 1, "byText") EndFunc ;==>_bbCourseSearchCategoryChange ;~ All exit commands, including F4, calls this function Func _Exit() Exit EndFunc ;==>_Exit  
      My main question is: How do I create an If... Then based on what is found in the search results? I need additional tasks to run if Col 1, Row 2 in the array contains the exact string I searched for. (Am I going about this the right way?)
      My next question (I might make a new thread for): How do I make the whole thing loop, as in, copy the next cell in the Excel sheet and do the whole thing over again until there's no more? I understand that a For/Next loop thingy would be used. I just don't know how. Loops are really confusing to me.
      Thank you all for your guidance and have a happy new year!
    • lattey
      By lattey
      hi,
      i have checkboxes and each checkbox that checked, i put in array. 
      now, im stuck on how to loop the checked array and store in in one variable. what i can do now, is only write the result into a text file. 
      below is the code:
      #include <GUIConstantsEx.au3> ;~ #include <MsgBoxConstants.au3> #include <ButtonConstants.au3> #include <Array.au3> Global $Count = 3 Global $CheckBoxP[$Count] Global $step[$Count] global $array1[1] Global $ExitResult $hGUI = GUICreate("Summary Steps", 500, 400) GUISetFont(12, 400, "Tahoma") GUICtrlCreateLabel( "Please Select the Summary Steps for Script Check", 70, 20) GUISetFont(10, 400, "Tahoma") Global $array_Pstep[3] = ["fix2","fix1","fix3"] global $step[3] = ["2","3","4"] $Spacing = 50 For $i = 0 To UBound($array_Pstep) - 1 $CheckBoxP[$i] = GUICtrlCreateCheckbox($array_Pstep[$i], 80, $Spacing + (20 * $i), 65, 17) Next $submit = GUICtrlCreateButton("Submit",180, 280, 80, 30) $exit = GUICtrlCreateButton("Exit",180, 320, 80, 30) GUISetState() While 1 $Msg = GUIGetMsg() Select case $Msg=$submit For $i = 0 To $Count - 1 If GUICtrlRead($CheckBoxP[$i]) = $GUI_CHECKED Then _ArrayAdd($array1, $step[$i]) EndIf Next Global $logfilerray = @WorkingDir & "\checkedlist.txt" FileDelete ($logfilerray) Global $readlogfile = FileOpen($logfilerray,1) for $a = 1 to UBound($array1) - 1 ;~ $var=$array1[$a] FileWriteLine($readlogfile,$array1[$a]) Next FileClose($readlogfile) Exit case $Msg=$exit $ExitResult = MsgBox(1,"Summary Step", "Continue to Exit ?") if $ExitResult = 1 Then ;ok Exit EndIf Exit EndSelect WEnd  
×