Auto hotkey - Splitting String and checking for numeric values - autohotkey

I'm a fairly new developer and i have run into a problem.
I'm using auto hotkey to automate at longer manual process, and one of the things i'm trying to do is split an address, and then use each individual part of that address in another system. The problem is that addresses can be very different.
I use Strsplit on the entire address, and then i want to check if each part of that address is numerical or a letter.
My problem is that no matter what i try. I always get the same result.
I use "if var is not type" and "if var is type". The problem is that not matter I check for alpha, integer, number or float it always returns true even if the variable is clearly a string and I check for numbers. Sample code below.
xl := ComObjActive("Excel.Application")
Array := StrSplit(xl.Range("C2").text, A_Space, ",")
if Array[1] is not number
{
Msgbox, False
}
if Array[1] is number
{
Msgbox, True
}
Can you help me?

To retrieve an array element use the := operator:
xl := ComObjActive("Excel.Application")
Array := StrSplit(xl.Range("C2").text, A_Space, ",")
element1 := Array[1]
; MsgBox, % element1
if element1 is not number
Msgbox, False
if element1 is number
Msgbox, True

Related

AutoHotKey if clipboard contains in array value

I am making a script for validating wallet cryptocurrency.
so whenever I copy the address wallet and then I run the script. if the address wallet same as the array value, it will show msgbox that give information about the wallet name. if not it will show n/a.
but I have some problems, where the msgbox shows based many numbers of the array
here is my code
^q::
walletAddr := Object("wallet1", "0x01415e36ce36d07229abf8b0435669088319f656", "wallet2", "0x9d6fb140607e1727c1373624a97ba681ef54f5bk", "wallet3", "0x660f01a47efd305862bc598cad44d1966b376d67")
found := 0
for k, v in walletAddr
if ( clipboard == v ) {
MsgBox % k
found := 1
}
if !found
MsgBox, n/a
return
and I figure out that this problem isn't from the script. but from the array value.
I try to change the value to a simple word and it works perfectly
walletAddr := Object("wallet1", 0xFF0000, "wallet2", 0x0000FF,"wallet3", 0x00FF00)
I have no clue where the problems come from. maybe it's because of length value, value typedata, or others.
can someone help me figure out my problem? thank you
i found tricky way to make it work :D
just add string text ( i use = "wallet_" ) before value and before clipboard.

Why is the key of my Associative Array a reference to a string and not the string itself?

I have the following string that contains product barcodes:
4016241030924;4016241030924;8710624237479;5900951254741;8710398162939;8710398162939;8710398162939;8710398162939;8710398162939;8710398162939;8710398162939;8710398162939;8710624296933;8710624296872;8710624223885;8710624223885;8711000341001;8711000341001;8711000341001;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260453;
What I want to do is:
Split the string by ;
Create an Associative Array where the key is the barcode and the value is the count of the barcode
Loop through the Associative Array and print the key (= barcode) and the value (= count)
Here's what I am trying:
BarcodesAssArray := Array()
BarcodeArray := StrSplit(fileContent, ";")
Loop % BarcodeArray.MaxIndex() - 1 {
thisBarcode := BarcodeArray[a_index]
; Check if barcode already exists
if (BarcodesAssArray[thisBarcode]) {
BarcodesAssArray[thisBarcode] := BarcodesAssArray[thisBarcode] + 1
} else {
BarcodesAssArray[thisBarcode] := 1
}
}
For key, value in BarcodesAssArray
MsgBox, %key% = %value%
But instead of the key being the barcode it is some sort of reference to the barcode. This is what I get:
-333809963 = 1
204486651 = 8
430547597 = 2
430561191 = 1
430584127 = 9
43084165 = 1
...
What I expect to get is:
4016241030924 = 2
8710624237479 = 1
8710398162939 = 8
...
What should I do differently?
Try to simplify the code and take it one step at time
BarcodesAssArray := 4016241030924;4016241030924;8710624237479;5900951254741;8710398162939
BarcodeArray := StrSplit(BarcodesAssArray, ";")
MsgBox BarcodeArray(1) BarcodeArray(2) BarcodeArray(3) BarcodeArray(4) BarcodeArray(5)
This will at least get you past the StrSplit statement knowing that you have a valid array
I haven't coded in a while so run at your own risk :)
"Your problem is probably occurring because the keys in your arrays are being treated as numeric. There are limits on the size of numeric keys, depending on whether you are using 32 bit AutoHotkey or 64 bit. The way I would fix this is to cause the keys to be treated as alpha by appending a constant alpha value to the key in the array and stripping it off when displaying, etc the key. This also deals with the case where leading zeros would otherwise be stripped from the numeric keys."
TAC109 - https://www.autohotkey.com/boards/viewtopic.php?p=312566#p312566
BarcodesString := "4016241030924;4016241030924;8710624237479;5900951254741;8710398162939;8710398162939;8710398162939;8710398162939;8710398162939;8710398162939;8710398162939;8710398162939;8710624296933;8710624296872;8710624223885;8710624223885;8711000341001;8711000341001;8711000341001;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260453;"
BarcodesString := RTrim(BarcodesString,";") ; remove trailing ;
BarcodesAssArray := {}
Loop, Parse, BarcodesString, `;
switch BarcodesAssArray.HasKey(A_LoopField . "")
{
case true:BarcodesAssArray[A_LoopField . ""] += 1
case false:BarcodesAssArray[A_LoopField . ""] := 1
}
For key, value in BarcodesAssArray
MsgBox, %key% = %value%
Xtra - https://www.autohotkey.com/boards/viewtopic.php?p=312565#p312565

Get First Character of A_LoopFileName?

I'm trying to parse a filename and get the first character from it as a string to compare it to a previously inputted variable. My code looks like:
FileSelectFolder, WhichFolder ; Ask the user to pick a folder.
; Ask what letter you want to start the loop from
InputBox, UserInput, Start At What Letter?, Please enter a letter to start at within the folder (CAPITALIZE IT!)., , 450, 150
if ErrorLevel {
MsgBox, CANCEL was pressed.
ExitApp
} else {
inputted_letter = %UserInput%
tooltip %inputted_letter% ; Show the inputted letter
sleep, 2000
tooltip
}
Loop, %WhichFolder%\*.*
{
current_filename_full = %A_LoopFileName%
files_first_letter := SubStr(current_filename_full, 1, 1)
tooltip %files_first_letter% ; Show the file's first letter
sleep, 2000
tooltip
if files_first_letter != inputted_letter
continue
...
Right now, it clearly shows in the tooltips the user-entered capital letter, and then the first letter of each file name from within the selected folder, but for some reason when the two look alike, it doesn't recognize them as a match. I'm thinking maybe because technically A_LoopFileName is not of a string type? Or maybe the inputted letter doesn't match the type of the first filename's letter?
I want it to continue if the inputted letter and the first letter of the filename don't match, but if they do, to carry on with the rest of the script. Any ideas on how I can get these two to successfully match? Thanks!
Firstly, AHK doesn't really have types. At least not how you've experienced types in other languages.
So your assumption about "not being correct type" will pretty much always be wrong.
So the actual cause is because in a legacy if statement, the syntax is
if <name of variable> <operator> <legacy way of representing a value>
So you'd do it like this:
if files_first_letter != %inputted_letter%
You we're comparing if the variable files_first_letter is equal to the literal text inputted_letter.
However, I highly recommend you stop using legacy syntax. It's really just that old.
It'll differ horribly much from any other programming language and you run into confusing behavior like this. Expression syntax is what you want to use in AHK nowadays.
Here's your code snippet converted over to expression syntax in case you're interested:
FileSelectFolder, WhichFolder
;Forcing an expression like this with % in every parameter
;is really not needed of course, and could be considered
;excessive, but I'm doing it for demonstrational
;purposes here. Putting everything in expression syntax.
;also, not gonna lie, I always do it myself haha
InputBox, UserInput, % "Start At What Letter?", % "Please enter a letter to start at within the folder (CAPITALIZE IT!).", , 450, 150
if (ErrorLevel)
;braces indicate an expression and the non-legacy if statement
;more about this, as an expression, ErrorLevel here holds the value
;1, which gets evaluated to true, so we're doing
;if (true), which is true
{
MsgBox, % "CANCEL was pressed."
ExitApp
}
else
inputted_letter := UserInput ; = is never used, always :=
Loop, Files, % WhichFolder "\*.*"
;non-legacy file loop
;note that here forcing the expression statement
;with % is actually very much needed
{
current_filename_full := A_LoopFileName
files_first_letter := SubStr(current_filename_full, 1, 1)
if (files_first_letter != inputted_letter)
continue
}
Also you don't have to be concerned about case with !=, it'll always compare case insensitively.

How to have "input" (or is it context?) dependent hotstrings/hotkeys ?

I want a hotkey or hotstring (whatever is easier), so I can easily convert e.g.
1:5 into [1,2,3,4,5] or
3:7 into [3,4,5,6,7] etc..
I want this to work for all integers...
So I want "multiple variants of the same hotstring" (or, if easier: a hotkey that works somewhat similar: e.g. pressing strg + h and typing 1:3 should produces [1,2,3] )
It should recognize that I typed a number followed by colon followed by another number, and then expand correspondingly..
I looked into the Input function, but it does not seem to be exactly what I want..
I don't need a working solution. Hints & links or keywords for further googling are already helpful..
After typing +h or pressing strg+h, type two numbers to produce the desired outcome:
:*:+h::
^h::
nr := "" ; empty variable's content
end_nr := ""
Input, var, L2 ; Length limit=2
; Input, var, L2 V ; V: Visible
If var is not integer
{
MsgBox, "%var%" is not integer
return
}
first_nr := SubStr(var, 1, 1)
second_nr := SubStr(var, 0)
if (first_nr >= second_nr)
{
MsgBox, "%first_nr%" is greater or equal "%second_nr%"
return
}
Loop
{
nr++ ; increase the number in the variable "nr" by 1 in each iteration
if (nr < first_nr)
continue
If (nr = second_nr)
break
end_nr .= nr . "," ; concatenate the outputs by adding a comma to each one
}
If (first_nr = 0)
MsgBox, "0,%end_nr%%second_nr%"
else
MsgBox, "%end_nr%%second_nr%"
return

Setting a control name with concatenated text+variable for ControlSetText usage

TL;DR I created a new variable (destinationControl) by concatenating a string, a separate string variable, and then another string. I tried using the variable destinationControl with ControlSetText, but its not working. Can anyone tell me why?
Long Explanation:
I'm attempting to send some data from an excel spreadsheet into another application using AHK ControlSetText. My issue comes in when I need the script to detect which one of two possible programs is the active one (the detection part is working) and then based on the name of the program, set the destination control name is slightly different.
prog_A_segment := "abc"
prog_B_segment := "def"
;determine which program is open
IfInString, OpenProgram, ProgA
{
ctrlSegment := prog_A_segment
}
else
ctrlSegment := prog_B_segment
;set control variable
destinationControl := "WindowsForms10.EDIT.app.0." . ctrlSegment . "_r13_ad11"
;activate program
WinActivate, % OpenProgram
WinWaitActive, % OpenProgram,,3
;open vendor form
Sleep 300
Send ^o
Sleep 200
Send Vendors
sleep 200
Send {ENTER}
Sleep 2000
;This does not work:
;pass information to vendor form control
ControlSetText, %destinationControl%, %myNumber%, %OpenProgram%
I know I could just slightly more manually set them based on the open program but i have about 25 controls in total and the only difference is that center segment so I thought this would be a little more elegant and cleaner.
When I use the above method it doesn't appear AHK can find the control. I'm assuming it has something to do with how I combined a string and a variable. Is there some way to make this approach work without doing this instead:
IfInString, OpenProgram, ProgA
{
destinationControl1 := "WindowsForms10.EDIT.app.0.abc_r13_ad11"
....
destinationControl25 := "WindowsForms10.EDIT.app.0.abc_d52_ad11"
}
else
destinationControl1 := "WindowsForms10.EDIT.app.0.def_r13_ad11"
....
destinationControl25 := "WindowsForms10.EDIT.app.0.def_d52_ad11"
I agree with Josh Brobst that your first piece of code would work with the missing quote added.
Well, here's what you want to try anyways:
ctrlSegment := InStr(OpenProgram, ProgA) ? "abc" : "def"
Loop Parse, % "r13, ... ,d52", CSV
ControlSetText % "WindowsForms10.EDIT.app.0." ctrlSegment "_" A_LoopField "_ad11"
, % myNumber, % OpenProgram