Page 1 of 1

Functions ARGH! Help with this simple SUM script pls?

Posted: Sun Jul 27, 2008 4:36 pm
by heatherbee
I am attempting a simple personal budget app that allows me to enter income in one list, and expenses in another. I want the totals to auto update as the fields are edited (ie no buttons required if possible).

I have put all the income amount fields into one group. I've done the same with all the expenses amount fields. I assumed this would make it easier to refer to in script?! Or is there an easier way to refer to a zillion fields at once to get their sum?!

I know I could just go and add up each field in one big long expression and get a result, but I'm on about day 4 of trying to wrap my brain around functions, and this project is supposed to be helping me learn. HA!

The income group is called "iList". Trying to display the total in field "iTotal" (will do the Expenses when got it working). I know the keyDown is probably NOT the correct message to use, and if not, what? Are there any field specific "field edit or change" messages available instead?

Anyway, no doubt I'm WAY off, but here goes (getting error of course):

By the way, this code is in the stack script because I wasn't sure about the best place yet? Is it okay in here? Sorry, still so much to learn... but really am enjoying the process!

Code: Select all

function addList groupName
  repeat with x = 1 to the number of items in groupList
    add item x of groupList to sumValue
  end repeat
  return sumValue
end addList

on keyDown theKey
  if theKey is a number then
  put addList(iList) into field "iTotal"
  end if
end keyDown
Any help appreciated as usual. :D I'm hoping I'm not TOO far off? :-P Gulp...

Posted: Sun Jul 27, 2008 10:24 pm
by BvG
Your problem is that you want to refer to fields, but only add items (of nothing), also your variable names are off. The following should work:

Code: Select all

function addList groupName
  repeat with x = 1 to the number of fields in group groupName
    add field x of group groupName to sumValue
  end repeat
  return sumValue
end addList

on keyDown theKey
  if theKey is a number then
  put addList("name of a group which contains fields") into field "iTotal"
  pass keyDown
  end if
end keyDown
As for where to put stuff, I'd put the keyDown into the group of fields, because then it'll also disallow non numerical entries there. If you'd put it into the stack script there can't be entered any chars that are not numbers in that stack (and if it has substacks, there neither).

The addList is fine in the stack, or the card, or the group. But if it's in the group there's no other place where it can be used but that group and it's controls, so that's often not the correct place for general functions.

Posted: Sun Jul 27, 2008 10:44 pm
by SparkOut
I started playing with a test stack, and in the meantime you have already got some answers, but I typed a reply anyway, so I'll paste it below, as there may be some other areas you want to examine (eg closeField)

Hi heatherbee

(so far as I know) keyDown or rawKeydown may or may not be the appropriate messages to check in your situation. The field change message that is sent when a user exits focus on a field is "exitField" if the contents have not been changed, or "closeField" if the contents have been edited or updated. It seems that you probably want the updating of the field to trigger the totalling, so I'd imagine that to be more appropriate to handling the "closeField" message on each field in the group, but keyDown may work in your situation. You will likely need to pass the keyDown message in your handler if you find that it's right for you.

To catch the message on the card, putting the handler in the stack or card script is fine. Perhaps it would be more specific (ie efficient - or handled earlier in the message path anyway) to have it in the card script, if there is no reason to have the same handler applied on a different card.

As to the totalling function, it seems like you have the right idea but need to check the syntax.

Code: Select all

function addList groupName 
  --firstly the groupName parameter is not referenced in this function
  
  repeat with x = 1 to the number of items in groupList 
  --you need to reference the groupName parameter passed to the function
  --which holds the name of the group to total
  --also, "items" are chunks of data in an expression
  --you need to reference the controls you are looking to total
  --ie fields, and identify them to the script
    add item x of groupList to sumValue 
    --item is a "chunk" (usually in a commas separated list) of data, not
    --the value held in the field you are trying to reference
  end repeat 
  return sumValue 
end addList 
If you try:

Code: Select all

function addList pGroupName 
  -- calling the parameter pGroupName is a convention I've adopted
  -- whatever the name, it must be the parameter you reference in the function

  local tLoop, tSumValue
  -- purely subjective preference, I always declare variables explicitly

  repeat with tLoop = 1 to the number of fields in group pGroupName
  -- loop through the number of fields, and identify the target
  -- it isn't enough to count the "number of fields in pGroupName" (to my knowledge)
  -- you should identify that pGroupName is a "group" in the syntax

    if the text of field tLoop of group pGroupName is a number then
    -- rather than "item" you need to retrieve the value of the control you have as the target
    -- ie the text of the field (numbered tLoop in the "group" pGroupName)
    -- after checking that it's a number, you can add the text (ie the value of the field) to the total
      add the text of field tLoop of group pGroupName to tSumValue 
    end if
  end repeat 
  return tSumValue 
end addList
you should get a better result.

Rather than handling a keyDown message, I put a closeField handler on each of the fields in the group which called the function.

Hope that helps

Posted: Mon Jul 28, 2008 3:08 pm
by heatherbee
Thanks for your help guys, I'll have a play around with this project again tomorrow after a good much-needed sleep!