So, I have a setup script that runs every time I open the program. I have 10 or so different fld variables that I want to add or remove from a group based on whether the number at the end of their id is less than or equal to the length of a randomly generated word, in this case known as the variable randomword. In case the letters are not in the group and therefore cannot be removed, I want to only try to remove it but if unsuccessful just move on to the next value of x. I know how to add something to a group, but not remove a single control from that group. How can I run a script so that:
for x = 1 to 10
put length(randomword) into tLen
if x <= tLen
copy fld ("letter"&x) to group "letters"
else
try:
remove fld ("letter"&x) from group "letters"
end if
end for
Everything below the else statement above is pseudocode as I don't actually know how to do that. Anyone with a working solution to this would make my day.
To delete a control from a group, use the delete command:
delete fld ("letter" & x) of group "letters"
Related
I want to create a Mac app similar to Textexpander or Atext. Both these applications allow the user to define snippets along with their respective trigger words. Typing the trigger words in any app, replaces that trigger word with the actual snippet defined.
I presume that the app listens to all strings being typed in any app and when it detects a string matching one of the trigger words defined, it replaces it with the snippet.
Is that how it actually works, or is there some other way?
Make two fields. In field 2 put something like:
time xyz
come ABC
In the script of field 1:
on textChanged
if the last char of me = space then
put the last word of me into temp
if temp is in fld 2 then
repeat for each word tWord in fld 2
put the last word of line lineOffset(temp,fld 2) of fld 2 into the last word of me
exit repeat
end repeat
end if
select after text of me
end if
end textChanged
Now type into fld 1, you know, "Now is the time for all good men to come to the aid of their country". This can be better done with an array, but the concept may be more accessible here.
This is a better handler, since it will not react to the trigger word:
on textChanged
if the last char of me = space then
put the last word of me into stringOfInterest
put fld 2 into dataToSearch
if stringOfInterest is in dataToSearch then
repeat for each line tLine in dataToSearch
if word 1 of tLine = stringOfInterest then
put word 2 of tLine into the last word of me
exit repeat
end if
end repeat
end if
select after text of me
end if
end textChanged
I'm creating a forecasting model for a fleet of equipment using Excel wholly written with VBA.
While forecasting the utilisation of equipment, some equipment will reach its replacement threshold and a new piece of equipment takes over from there. This will require a new row added to the table for the new equipment.
I would have thought that a For loop would be dynamic, so using a variable for the upper limit would be re-evaluated on every loop, but this seems not to be the case.
I set up a simple scenario to test as per the code below, starting with 2 listrows in the table.
Sub Test1()
Set Table1 = Sheet1.ListObjects("Table1")
x = Table1.ListRows.Count
For i = 1 To x
Set NewRow = Table1.ListRows.Add
x = Table1.ListRows.Count
NewRow.Range(1, 1) = x
Next i
End Sub
I assumed it would run infinitely but it will only run as per the initial case provided.
Is using a different type of loop (Do While or Do Until) the ONLY way to achieve a genuinely dynamic outcome?
To sum things in the comments to your question up:
Modifying the target of a for-loop might be prohibited in Viual Basic. There are other languages out there that in principle allow for this kind of operation, however, it's not a good programming style.
The reason is, that a for-loop is a loop counting over a fixed interval (that should not change during the loop's execution).
Instead of using a for-loop here, one may consider using a while-loop:
i = 1
While i <= x
Set NewRow = Table1.ListRows.Add
x = Table1.ListRows.Count
NewRow.Range(1, 1) = x
i = i+1
Wend
Caution:
This loop will run forever (or rather: until you reach a maximum of resources, in which case it will crash). The reason is, that you move the upper bound for the iteration 1 unit further away while approaching it by 1 unit.
The best way to approach what you actually want to achieve is using a buffer list:
Identify the items you want to create a new row for
Insert that row into a second list
Iterate over the second list and append the items to the original list
This way, you avoid testing the newly inserted items (which most likely won't be outdated by now).
I want to use applescript to do a periodic (every second) check to see if a specific bluetooth devices is connected, and if so, to flash up a quick notification. To frame it, I want a popup when my Airpods connect, since sometimes when I pull them out, the connect to my computer, and sometimes to my iPhone.
I've got everything figured out, except for the bluetooth check part. I've used this as a starting point, but can't get it to work. Any help would be appreciated.
repeat
set statusOld to checkStatus()
set statusNew to checkStatus()
repeat while statusOld is equal to statusNew
delay 1 --for 1 second checks
set statusNew to checkStatus()
end repeat
if statusNew is true then
display dialog "Device Added - put some real code here"
else
display dialog "Device Removed - put some real code here"
end if
end repeat
on checkStatus()
(*Delete the 2 lines below when done testing*)
--set myString to button returned of (display dialog "Connected?" buttons {"Yes", "No"})
--set myString to "name: DR-BT101 Connected: " & myString
(*uncomment line below when done testing*)
set myString to do shell script "system_profiler SPBluetoothDataTyp"
--initial check if it's not even there
if myString does not contain "Christian’s AirPods" then
return false
else
--find out if connected/disconnected
set AppleScript's text item delimiters to "name:"
set myList to the text items of myString --each item of mylist is now one of the devices
set numberOfDevices to count of myList
set counter to 1
repeat numberOfDevices times --loop through each devices checking for Connected string
if item counter of myList contains "Christian’s AirPods" then
if item counter of myList contains "Connected: Yes" then
return true
else if item counter of myList contains "Connected: No" then
return false
else
display dialog "Error Parsing" --this shouldn't happen
end if
end if
set counter to counter + 1
end repeat
end if
end checkStatus
You're missing the e:
set myString to do shell script "system_profiler SPBluetoothDataType"
^
I'm working on something similar. This seems to work well on macOS Mojave:
use framework "IOBluetooth"
use scripting additions -- https://stackoverflow.com/a/52806598/6962
on isDeviceConnected(substring)
repeat with device in (current application's IOBluetoothDevice's pairedDevices() as list)
if device's isConnected and (device's nameOrAddress as string) contains substring then return true
end repeat
return false
end isDeviceConnected
-- Usage example:
isDeviceConnected("AirPods")
I combined it with a launch agent like this: https://gist.github.com/henrik/3d4c622a5567cdf2bf461352f48ad4dd
I'm working making a loop to get data out of a combo form.
Analysis_1 is the first variable
Analysis_1_ComboB is the first ComboBox from the screen
Analysis_1 = Me.Analysis_1_ComboB.Column(0)
Analysis_2 = Me.Analysis_2_ComboB.Column(0)
Analysis_3 = Me.Analysis_3_ComboB.Column(0)
etc etc
as single lines, it is working I do want to work with a loop
for counter = 1 to 9
Analysis_&Counter = Me.Analysis_&Counter&_ComboB.Column(0)
next counter
unfortunately, this is not working, who can help me out here?
Unfortunately, you cannot dynamically specify variable names. (You can usually find a way to dynamically access various objects, especially if they are accessible be a "Name" index.)
The best way to achieve what you want to do is make your variables an array, e.g.:
Dim Analysis(1 To 9) As String
For counter = 1 To 9
Analysis(counter) = Me.Controls("Analysis_" & counter & "_ComboB").Column(0)
Next counter
MsgBox "Value from Analysis_5_ComboB is " & Analysis(5)
(This code assumes that your ComboBoxes are on a UserForm and therefore dynamically accessible via the form's Controls collection.)
How to delete a row in datagrid. I am using the following code and it's not working(first two lines are working and the 3'rd line is not working) how i change my code.
put the dgHilitedLines of group "DGP" into theLine
answer theLine
DeleteLine theLine
Delete line in DataGrid with Dispatch command is needed in case you do this outside the datagrid. E.g. with a button outside the datagrid.
on mouseUp
put the dgHilitedLines of group "DGP" into theLine
answer "The selected line var is : " & theLine
dispatch "deleteline" to group "DGP" with theLine
put the result into tDeleteresult
if tDeleteresult is not empty
then
answer "There has been a problem deleting the line with message: "&tDeleteresult
else
answer "Line Deleted"
end if
end mouseUp
Did you try using the index instead of the line?
put the dgHilitedIndex of me into theIndex
DeleteIndex theIndex
The line is always the current display order, say
A = 1
B = 2
C = 3
Thus if you delete line 2, the next line C will become line 2. This is usually a bit of a problem.
After delete line:
A = 1
C = 2
The index on the other hand is assigned when you fill the datagrid and stays the same for one row, no matter how you sort it. This way you can always identify that row
With index:
A = 1
B = 2
C = 3
After delete row 2:
A = 1
C = 3
I always, as a matter of practice, do this sort of thing in the clear. The tools and analytics within LC proper are far more accessible and powerful than within the DG itself.
So in general:
get the dgData of group "yourDG"
delete line whatever of it
set the dgData of group "yourDG" to it
Craig Newman
Same answer as MrCoolLion in a more concise way:
put the dgHilitedLines of group "DataGrid" into theLineNo
dispatch "deleteline" to group "DataGrid" with theLineNo