Using Functions in IF Condition Statements

Functions are procedures that return a value after performing some special operation. These functions can be used anywhere within a condition or expression statement.

The syntax for a function is:

Function name(argument)

The function name comes first, immediately followed by a left parenthesis, the argument(s), and a right parenthesis.

Note: The function name must be directly before the left parenthesis.



Some functions are sub-functions called “Extended Functions” and use XF() around the function name. The full “extended_function()” syntax is also allowed.



The IFTHEN and IFTHENELSE functions are used to return numeric values and expressions based on some condition. Both are generally only used with expression statements.

Here is the syntax for the IFTHEN function and an example of its use for the return of numeric values:

IFTHEN(logical expression,numeric expression)



A logical expression is any expression that can be resolved as either true or false; a numeric expression results in some numeric value. IFTHEN() returns the value of the numeric expression if the logical expression is true; otherwise, zero is the result. In the example above, the result will be 50 if the response to Question 5 is greater than 10; if the response to Question 5 is less than or equal to 10, or missing, the result will be zero.

The IFTHENELSE function returns the value of expression1 if the logical expression is true; otherwise, the value of expression2 is returned. The syntax and an example are given below:

IFTHENELSE(logical expression,numeric expression1, numeric expression2)


!IF IFTHENELSE(Q5>10,50,75)

In the example, the result will be 50 if Question 5 had a response greater than 10. If the response to Question 5 was less than or equal to 10, or missing, the result would be 75.

In addition to numeric values, the “IFTHEN()” and “IFTHENELSE()” will let you do more complex conditions using question labels within the function.


{ QXX: .2

This example indicates that if Q6 is a response code of 1, then multiply the numeric value of Q7 by 2 and put the resulting value in field QXX. And, if Q6 was not a response code 1, then put the value of 3 in the field QXX.

For example, the ELSE portion of the function can be used to assign nonzero values to special codes such as Don’t Know or Refused.


LOCAL_SCRATCH(start, length)

Shortform: LOCALSCR

Returns the contents or a region of the local scratch area, a memory area available during a particular Survent session. You must refer to it using the syntax for string or literal data.



If the data in the local scratch area in column one for the length of two is equal to the literal 34 then execute the question. Data gets into and out of the local scratch area by using SPECIAL subtypes K and L (see Special Information Statements).


!IF LOCAL_SCRATCH(3,4)=[1.4$]

This example is comparing what’s in the local scratch area columns 3-6 (three for a length of four) with what’s in the data in columns 1-4.



This function returns the location of a variable during a Survent interviewing session. Typically this would be used with utility applications where you are trying to check the input to a variable and want to display the place where the error occurred.




MAX(numeric expression 1,numeric expression 2, numeric expression n)

Returns the highest number from the numbers specified. The numbers specified can be labels, location references, absolute numbers, QUOTA() functions, etc.


!IF MAX(23,[10.3],QAGE)>MIN(Q1,Q2)

This would cause question execution if the maximum value of the first group of references was greater than the minimum value of the second group.


MIN(numeric expression 1,numeric expression 2, numeric expression n)

Returns the lowest number from the numbers specified. See MAX above for example.



Returns a random number between zero and the number specified. This can be used as a rotate controller (See Rotations). It is usually used only with expression statements, not IF conditions.


!IF RANDOM(9)+1>3

The statement would execute if the random number returned plus one is greater than three; in other words, approximately 70% of the interviews would execute this statement.

Notice that you can control the range of the numbers returned by doing an arithmetic operation. In the example above, a number from one to ten was being returned. The number in parentheses controls the high point of the initial range (0-9) and the +1 changes the range (1-10).

The random function will take as an argument a numeric expression.




This function reads any variable or function and returns it as a numeric value if the result is a number. For instance it will read ”  1  ” and return it as ”    1″ (a right justified numeric 1).

Its uses include:

  • Converting the value of a string function to a number.
    • For instance, XF(STRING_TO_NUMBER(LOCALSCR(5,3)) returns the number in column 5 for a length of 3. Otherwise the function result is always considered a string.
  • Since it right justifies the value first, this function can be used to read a VARIABLE type value that is left justified and return the value as a number.
    • e.g., the result of a VARIABLE,NUMERIC_ONLY response.


Records the time spent on any particular web page in a survey. The value returned is a value in seconds.


{ Q1TIME: .5



Returns the width of a variable during a Survent interviewing session.


{ Q23WIDTH: .5

X(label or [location])

Returns a zero if the question’s response is blank or non-numeric, otherwise the number (numeric value) at the location specified. This is useful for questions that have skip patterns around them, but must still be used in calculations or comparisons.


!IF X([10.2])+X([QAGE])>33

If the data in columns 10 and 11 plus QAGE is greater than 33, execute the statement. If one of the items is blank, it is treated like a zero, and the test can still be done.

If used on a FIELD question, X will return the numeric value of the response code(s), if any, or zero (if blank). Multiple responses will show up in one of the following ways:

  1. If two responses are allowed and two are given, the combined value will be used.
    1. For example, responses 01 and 02 will return 0102.
  2. If fewer responses given than allowed, 0 will be returned.
    1. For example, response 05 with the next set of columns blank (“05”) will return 0.
  3. If the responses are non-numeric, 0 will be returned.

Response-Checking and Counting


CHECKTEXT(TEXT question label or [location])

Returns the number of characters entered as a response to a TEXT type question. If the question was not asked, a -1 is returned. If the question was asked but not answered (TEXT,B), a 0 is returned. If it was answered, 1-5000 is returned. This is used to determine whether to edit the question later (if many characters), or just to see if a response was given.




XF(COMPARE_FIELDS(<field expression>))

Shortform: XF(COMPARE_FLD())

Allows for checking whether a code in one list is also in the other list, whether two lists match, whether their code sets intersect, or whether one list is a subset of the other.



This returns “true” if the same codes are in Q23 and Q24.  The available operators and their meanings are:

=  equals, matches
<> does not equal
<  less than
>  greater than
>= greater than or equals to
<= less than or equals to
intersect Some code(s) is/are in both code lists but other codes could also be present

The questions referenced must be FIELD questions.  If one of the two questions is blank the usual rules for sets apply: blank = blank, blank >= blank, blank <= blank, A > blank, A >= blank, A <> blank, A does not intersect blank.

You can also use a SUBSET of a list as part of a comparison, for example, to exclude the “Don’t know” code from a comparison:


!IF XF(COMPARE_FIELDS( Q23(1-5,9)=Q24(1-5,9) ) )

This returns “true” if the same codes between 1-5 or 9 are in Q23 and Q24, even if there is some other code that is not specified in the subset list in one or both of the questions.

Note: The “Intersect” keyword returns the # of items that intersect, all others return “1” for true and “0” for false.


XF(MATCH_TEXT(TEXT or VARIABLE label or [location], “string 1” ,” string 2”,” string n”))

Shortform: XF(MTCHTXT(<label/[location]>,”string 1”,”string 2”,” string n”))

Returns the position of a string or set of strings in the answer to long or short open-end questions. It returns the position of the first string if it finds that, otherwise the position of the second string, etc.  The function returns a 0 if no strings are found.

If more than one string is present, it returns the position of the first string even if it is at a later position than the second. Use this for automated coding applications or to ask follow-up questions based on references to a client product, for instance. You could use multiple strings to check other spellings of the same product. The maximum string length is 80 characters.


XF(MATCH_TEXT(Q23,"Look for this","a,b","some other string"))


Returns true or false depending on the condition. Returns the opposite of the result of the condition.

The condition can be any number of valid conditional statements.



This executes the statement if QAGE is not greater than 34 and QSEX is not M.



Shortform: XF(NUM_RESP([label])

Returns the number of responses in a FIELD variable.


Which of the following beverages did you drink in the past 24 hours?
01 Coca-Cola
02 Pepsi
03 7-up

Which beverage did you enjoy the most?

QFAVORITE will only be asked if more than one response was given to QBEVERAGES. This function will count response codes whether they are numeric, alphabetic, or a combination of both.


NUMITEMS(label or [location])

Use the XF(Number_of_Responses()) function to count responses to a FIELD question.



This function counts characters in a string.  It functions similarly to the character count in a TEXT question with the CHECKTEXT() function, but works for other data types.



This requires a question label, a quoted string, or a string variable reference, and the question label used must be a VARIABLE or TEXT type question.


Adds 1 to a number every time you go over a question with this function. If you go over it once, back up, go over it again, it returns a “2”.

NOTE: Other Survox statements are cleared when you back over them.


{ QTIMES: .2



XF(MASTER_QUOTA,<label or [location] or  quotaname>,MODIFY)

Returns the value at the beginning of the interview of the named master quota.  The optional MODIFY argument returns the value of the change in the master quota since the beginning of the interview:




During an interview where the value of the OVERALL_FEMALES quota in the master quota file was 50 at the start of the interview, and 55 at the time these expressions were executed, the value of OVERALL_FEMALE would be 55 and OVERALL_FEMALE_CHANGE would be 5.



Returns the change in the named quota (in this case, as held in memory) since the beginning of the interview.



This example executes if the quota for MALES had been updated more than once (by having multiple quota incrementing statements) since the beginning of the interview. This will not be true for quota updates done using the “NOW” parameter (e.g., !QUOTA,1,name,+1,NOW). In this case the quota file is updated directly, but not the local quota value.


MODQUOTN(quota number)

Returns the change in the numbered quota (in this case, as held in memory) since the beginning of the interview.





Returns the value at the beginning of the interview of the named quota (see Quota Incrementing Statements), or at the time last read with a READ_NAMED_QUOTAS compiler command (see Interview Control Commands).



This would execute if the quota for MALES was greater than or equal to the target quota MALES.T.


XF(QUOTA(<label or [location] or quotaname>))

This returns the quota value of a quota whose name has been specified in a prior question or location. Here is an example that checks a quota from the sample file vs. its target quota:




Over quota for quota \|QUOTANAME|, thank the respondent and terminate.

NOTE: You can also use this function in the same manner as the QUOTA() function. That is, if you just put the label of a quota in parenthesis, it will check that particular quota. If you put a reference in brackets, it knows to check the data location of the specified location or label for the name of the quota to check the value of.


QUOTN(quota number, [location] or label)

Returns the current value of the numbered quota specified. The numbered quota can be referenced specifically, or as a number stored in a question label or data location (See Quota Incrementing Statements).


!IF QUOTN([123])>82

This says if the quota number stored in column 123 has a value greater than 82, execute the statement.

NOTE:  Using this repeatedly may slow down the system.



Returns the current value of the specified quota.

NOTE1: Using this repeatedly may slow down the system.

NOTE2: Best practice is to use the READ_NAMED_QUOTAS compiler command instead.

Phone File-Related



The DIALER function tells the program whether the interview is being controlled by a dialer. It returns a “1” if predictive mode, “2” if preview mode, and “0” if neither.



The FONESTATUS function is used to return the current status of the phone record. This function is often used with a predictive dialer to see if a status has been returned.  A “0” is returned for non-predictive dialer systems unless a PHONE,SET_CALL_STATUS statement has set a status.




FONETEXT(column, width)

The FONETEXT function returns the contents of the specified field in the phone file.



The above example will be true if “zoo” is in column 60 of the fonetext area of the phone file.



The LAST_CALL function says whether or not you are on the “LAST CALL” for the phone number you are calling. By last call we mean that after this call the phone record will be resolved with status 973 because its maximum number of calls will have been reached if it is a system call. It returns a “0” if it is not the last call, and a “1” if it is. This is used for advanced programming of call statuses based on whether the call is the last one or not.


XF(MARKET_WEIGHT(<marketname or <data label or [location>]>))

Shortform: XF(MKTWT((<marketname or <data label or [location>]>))

This returns the value of a particular market weight. You can either refer to a particular market using “marketname” or refer to a market name stored in the data using the “label or [location]” syntax.


This returns the “Maximum Attempts” setting from the phone file, which is the maximum times you can call a particular phone number. You can then look at this value to determine how to status the current call.

This function allows you to include maximum_attempts as one of the possible resolved statuses so you can do something based on that criteria (e.g., add a new phone record with the !PHONE,ADD_NEW_NUMBER statement).

NOTE: Survent picks up the fone header at the start of the interviewing session, so the value is whatever it was at the session start.


This returns how many times the number has been re-dialed during the current interviewing session by  using the “REDIAL” command or automatically.



You can now reference all the standard phone variables and custom variables you have described in fonebuld when referencing the data in the sample records.

The syntax for the XF(PHONE_DATA) function is:

XF(PHONE_DATA(<variable/location><+(offset)><.(length)>,"string") )


You are calling Survox.

You can reference any of the standard variables Survox supports on the PHONE,GET_PHONE_INFORMATION and PHONE_PUT_PHONE_TEXT statements and in select statements in FONEUTIL and the supervisor. You can use variable names or fixed locations, e.g., “PhoneNumber” or “1”.  You can, for example, use “+5” to offset the starting location by 5 and “.5” to reference 5 columns of data in the variable (see The Phone Record Format).

Note: In order to use your “Custom” variable names described in FONEBULD, you need to have the keyword “Get_Phone_Variables” specified in the questionnaire header.



Returns the current value of various phone header options. In particular, it returns the 4 digit military time of all the shop open and shut times, along with all the daypart times and the value of last scheduled. That data then can be used to check and make sure any automated call back time is within the current restrictions of the study.

valid keywords are:

LAST_SCHEDULED (Note: Last_Scheduled returns a 12 character field (YYYYMMDDHHMM) in military time.


{Shop_Shut_Sunday: .4

This would store the current value of the Shut time for Sunday in the variable Shop_Shut_Sunday.


This function can be used if you are trying to schedule calls and want the interviewer to be able to know how many calls have been scheduled at that time so far. Typically it is used in an EXPRESSION statement.


XF(TIMED_CALL,<time to get>)

Where <time to get> is a standard Survox date/time string.  The program reports any time you want and will return the number of numbers scheduled for that time.  Here is an example script reporting in 5 minute increments for whatever hour of whatever day you want the information for:

Which Date

What Hour
!NUMERIC,,1-12 }

AM or PM

>Repeat $a=00,05,...,55;

{ WDV$a: .5


>Repeat $a=00,05,...,55;
\:QWHICHDATE: \:QWHATHOUR::$a\:QAMPM: calls scheduled: \:WDV$a <br>

The function will return negative numbers on errors:

-1: no date
-2: no phone header
-3: manana_days not set
-4: error parsing date
-5: unused
-6: date before current time
-7: date beyond manana array size (see fonebuld 'manana_days' command)
-8: current time is after time when call can be scheduled
-9: date is after study shutoff time

Also see the features “manana_days=<1-60> in FONEBULD which you need to use to allow this feature, and “show_manana” in the supervisor to show the same information (number of calls scheduled by hour for X days).

NOTE: The default for “manana_days” is 7 days, so you get a list of at least the next week’s calls.

Date-Time Functions


XF(DATE_TIME_DIFFERENCE(datetime1, datetime2, type returned))

Shortform: (DATE_TIME_DIFF( datetime1, datetime2, type returned ))

This function returns the difference in 2 date/time strings in years, months, weeks, days, hours, minutes, or seconds. It reads two dates and a keyword and then returns a value. The dates can either be actual dates, or they can be question labels or [location.length] references where the dates are stored.

The date strings must be dates in the format YYYYMMDDHHMMSS. This is the same format returned by the !SPECIAL,JULIAN_DATE_TIME statement. The string must have as many characters as the keyword requires, for instance, if you want to return seconds, you need all 14 characters, but to return days you only need 8 characters.

The <Keyword> is one of Seconds, Minutes, Hours, Days, Weeks, Months, or Years. The value returned is the difference from Datetime1 to Datetime2. If Datetime2 is more recent than Datetime1, a negative value is returned. If the difference is 59 minutes and 59 seconds, it returns 0 for the number of hours and 59 for the number of minutes. If you are looking for rounding, you will need to use the next keyword and see if its value is over half of what is needed to kick the next value (i.e. >= 30 minutes) and add 1 to the value if true.

Datetimes are only compared on the shorter of the two values. For instance, if Datetime1 has only a date and Datetime2 has both a date and time, then only the days/months/years values will be nonzero, regardless of the time on Datetime2. Hours, minutes, and seconds will return “missing” in this case.

If either string has more than 14 characters, extra characters are ignored.  If either string has less than 4 characters, this is a spec error.



This would return the number of days since the born date to today’s date.

Note: A !PHONE,CONVERT_TO_RESPONDENT_TIME statement can be used to convert the respondent time and write it into a data location.  The information can be used for the date functions.  See below.



CONVERT_TO_RESPONDENT_TIME takes the time specified by the FROM location, converts it to respondent time, and puts it into the data location for this PHONE question.

The date/time in the FROM field must be 12-18 characters in the format YYYYMMDDHHMMSSXJJJ which matches the standard SPECIAL,JULIAN_DATE date/time format. If the date/time in this location is bad, then (BAD DATE) is put into the data. The width of the receiving location must be 12-18.

The syntax for the PHONE,CONVERT_TO_RESPONDENT_TIME question type is:





In this example, the time taken from 100.18 will be converted into the respondent’s time and stored in data location 200.18.


XF(DATE_TIME_OFFSET(place to save date, date to compare, type of return, # to offset by))

This function return a dates in the format YYYYMMDDHHMMSS given a starting date (YYYYMMDDHHMMSS) string and the amount to offset it by in years, months, weeks, days, hours, minutes, or seconds. The adjustment value can be positive or negative depending on whether you want to go forward or backwards in time.

You may use a datetime string that is shorter than 14 characters, but you must give enough characters in the string to match the keyword. For instance, if you add hours, your starting date must include hours.



This would return a date 15 weeks after the date in the question labeled “olddate” into the question labeled “newdate”.



This function returns the day of the week associated with the date specified. “Date” can be an actual date, or it can be a label or [location.width] where the date is stored. You must have at least YYYYMMDD in the date field, but can use up to a 14 character datetime string in the format YYYYMMDDHHMMSS.


{ DATE: .8
20040121 ''Put date in data

{ DAYOFWEEK: .1 ''Record the day of the week

This would return a “3” for Wednesday. Monday is 1, Sunday is 7.


TIMEDIFF (<[location] or label 1>,<[location] or label 2>)

Returns the difference of two times in seconds. The first time specified should be the later time, while the second time should be the earlier time. Both times must be in the format YYYYMMDDHHMMSS.


!IF TIMEDIFF([10.14$],[30.14$])>60

This states that if there is more than one minute between the time specified in location 10.14 and the time specified in columns 30.14, execute the statement (TIMEDIFF subtracts TIME2 from TIME1).  The maximum value returned from TIMEDIFF is 10,000,000 minutes (20 years). Use an EXPRESSION to divide the result by 60 to get minutes or use dump switch >dump S7.

Mode-Checking Functions



Returns a “1” or “true” if the interview is using the random data generation operation (see Random Data Generation), “0” if not. This is used to skip questions (e.g., screener questions) or other things that random data generation would not work well with. There are no arguments between the parenthesis.



This would go to the question FIRST if random data generation was being done, otherwise continue to the next question.



Returns “1” if the study is using a predictive dialer, “2” if it is using a power dialer (MSG dialer only, and “0” (“false”) if not. This is used in cases where users have alternate code for the study with different dialer types or without a dialer.


Shortform: XF(DT)

Returns “”0” if no dialer present, “1” if SER dialer, “2” if PRO-T-S dialer, “3” if NOBLE dialer, and “4” if Stratasoft dialer. This is used in cases where users have alternate code for the study with different dialer types or without a dialer. Other dialer types will be added as supported.



Returns the amount of time monitored in seconds:



You would want to put this statement at the end of the questionnaire to get complete monitor time.



Records the number of monitors during an interview.



Returns the current number of CATI interviewers on the study or the current number of respondents who are in the “heldin” queue waiting to be transferred from the IVR to a live interviewer. This function is useful when doing “blended” studies where respondents are initially connected to the IVR (inbound or outbound) and then want to be transferred to a live agent. This allows you to better manage the respondent experience, for instance, if there are no CATI interviewers currently on the study you likely would not want to even give the respondent the option to transfer out of the IVR. The keyword CATI_interviewers returns the number of CATI interviewers and the keyword Waiting_Respondents returns the number of respondents in the wait queue.

Valid keywords are:


{Current_Number_Interviewers: .4
!Expression,,XF(Survent_Count(CATI_Interviewers)) }

If this value were 0 for instance, you would not want to give the respondent currently in the IVR block the option of transferring to a live agent, so no agent will be available anytime soon.



This allows us to, for instance, have the survey play back a sound recording of the survey during the view process.  In this way you don’t have to write a separate coding-mode application to find the case and play back the sound while reading the responses.  You could also collect viewer responses and notes and add them to your dataset as part of the viewing process.



Returns a “0” if the interview was not monitored, a “1” if the interview was monitored, and a “2” if it was partially monitored.



The webSurvent() function returns codes specifying what mode you are in and why you are being suspended. The return codes are:

1 Running in webSurvent mode
2 Suspended in webSurvent or webCATI
4 Was suspended due to a suspend timeout (also known as “autosuspend”, where the survey was suspended because no response was given in the last 30 minutes or so) in webSurvent or webCATI
8 Running under webCATI
16 Running as a web utility (eg. ”&&&phrpt.qff” to run PHONERPT under Mentor)
32 Suspended because there was a webSurvent or webCATI killed session

For instance, you can use !IF WEB_SURVENT()=1 in the SUSPEND block to control any features you have that should only be invoked when suspended by an interviewer and NOT when autosuspended.

NOTE: For more examples that use these functions, see Data Generating Statements and EXPRESSION Statements. 



Records the phone extension of the monitor.

System-Related Functions



Shortform: XF(PID)

Returns the process ID of the current Survent session. This can be used for accounting or to remove process IDs that are not active. You can use this with IF conditions and EXPRESSION statements.


XF(USABLE_STUDY(questionnaire filename))

Returns a “1” if the questionnaire file is present, and a “0” if not. This is usually used when you have a list of studies for the interviewer to choose from and have CALL statements to execute the questionnaire if it exists.