ExpressionScript 示例
From LimeSurvey Manual
结构
本文第一部分介绍表达式的用途,以及在哪里查找/添加表达式。第二部分提供表达式的使用示例。
表达式的类别
LimeSurvey 将表达式用于以下用途:
关联
用途:隐藏题组/问题
关联用于控制题组或问题是显示还是隐藏。如果表达式的结果为“true”(即 1),则该元素将显示;否则(即表达式的结果为“false”,也就是 0),该元素将被隐藏。
| 类型 | 显示/隐藏 | 在哪里找 | 屏幕截图 |
|---|---|---|---|
| 问题组相关性 | 问题组 | 创建/编辑问题组 - > “相关方程:” | |
| 问题相关性 | 问题 | 创建/编辑问题 - >“相关方程:” | |
| 子问题相关性 | 子问题 | 编辑子问题 - >“相关方程:” |
验证
用途:验证对问题/子问题/答案的输入或操作
验证用于控制受访者在问题中的输入或操作是否有效。如果表达式的结果为“true”(即 1),则“good”类将应用于该元素和验证消息;否则,如果表达式的结果为“false”(即 0),则“error”类将应用于该元素和验证消息。您可以在 template.css 中为这些类定义样式。
| 类型 | 验证对象 | 查找位置 | 截图 |
|---|---|---|---|
| 问题验证 | 问题 | 创建/编辑问题 -> “逻辑选项卡” -> “问题验证等式” | |
| 子问题验证 | 子问题 | 创建/编辑问题 -> “逻辑选项卡” -> “子问题验证公式” |
文本输出
用途:(执行某些操作并)输出一些文本
表达式可用于输出文本。例如,您可以进行测试或计算,并根据测试或计算的结果指定输出内容。它还可以用于插入在该表达式之前使用的问题的问题文本、答案、问题类型等。文本输出可用于任何显示文本的位置,并可返回各种结果。
| 使用场景 | 描述 |
|---|---|
| 微调定制 | 调整文本,例如,根据之前提出的性别问题,输出“先生”或“女士” |
| 计算 | 计算一个值并输出,例如“您的家庭收入为 xxx” |
| 引用 | 插入某个元素中的文本,例如“您的姓名是 xxx。您多大了?” |
答案存储
用途:(执行某些操作,)(输出一些文本)并将内容存储到数据库中
方程式问题类型可用于将内容存储到数据库中。您可以通过表达式执行某些操作,显示方程式问题(类似于文本显示),并将表达式的结果存储到数据库中。答案将存储在响应表中。之后,该结果可用于统计功能,也可以导入到 LimeSurvey 导出功能提供的某种格式中。
表达式示例
插入上一个问题的答案
| 用途 | 插入上一个问题的答案 |
| 类型 | 引用 |
| 示例 | 问题一(问题代码“Q00”):您居住在哪个城市? 问题二(问题代码“Q01”):您在 CITY 居住了多久? 目标:使用问题一的答案替换第二个问题中的“CITY”。 |
| 表达式 | {QOO} |
| 描述 | Q00 中提供的答案将替换第二个问题中的 Q00 字段 |
| 步骤 | 创建/编辑问题二 在问题文本字段中输入“您在 {QOO} 居住了多少年?” |
| |
使用隐藏的方程式问题自动填写答案
问题: 假设您有两个问题 Q1 和 Q2。Q1 询问受访者的年龄。Q2 将受访者分为三组:年龄小于 20 岁、年龄等于 20 岁、年龄大于 20 岁。 因此,Q2 应使用与上述条件对应的值“1”、“2”、“3”。此外,别忘了将 Q2 设为不可见(该问题不会在调查中显示,但这些值会通过“后台进程”保存到响应表中)。
使用方程式问题类型填充数据库:
- 首先,创建一个问题代码为 Q1 的数字输入问题。
- 然后创建另一个问题代码为 Q2 的方程式问题。
- 在 Q2 的“显示设置”选项卡中:
- 将“始终隐藏本题”字段设置为“开”
- 在“方程式”字段中输入以下表达式:
{if(Q1.NAOK < 20, "1", if(Q1.NAOK > 20, "3", "2"))}
使用占位符创建摘要页面
本教程演示如何通过 ExpressionScript 占位符 在调查结束时创建概览,列出所有问题和答案。 同时还演示了如何将此类概览限制为仅显示已回答的问题。
您可以从这里下载我们的示例:调查占位符示例调查。
此处使用的问题类型:
1. 单选题 / 单文本/数字问题
- 列表(下拉)
- 列表(单选) [L]
- 是/否 [Y]
- 长自由文本 [T]
- 短自由文本 [S]
- 数字输入 [N]
- 方程式 [*]
2. 带子问题的问题
- 多短文本 [Q]
- 多选题 [M]
- 阵列 [F]
- 阵列 (是/否/不确定) [C]
- 阵列(10分制选择题) [B]
3. 带两个尺度的问题
- 阵列双尺度 [1]
4. 带 X 和 Y 尺度的问题
- 阵列(数字) [:]
5. 掩码问题
- 文本显示 [X]
在这个简单的示例中,我们的概览将是一个简单的列表,格式如下:
- 问题文本:用户的答案
单选题 / 单文本/数字问题
对于以下所有问题类型,LimeSurvey 只会存储一个反馈:
- 列表(下拉)
- 列表(单选)
- 带评论的列表
- 5分制选择题
- 是/否
- 短自由文本
- 长自由文本
- 巨大自由文本
- 数字输入
- 方程式
- 日期
- 性别
假设该问题的问题代码为 q1,我们可以使用以下方式引用问题文本和答案:
- {q1.question}: {q1.shown}
示例:
- 您多大年龄?: 25
如果您想检查该问题是否已被回答,可以在输出外围添加 IF 语句:
{if(!is_empty(q1),join("- ",q1.question,": ",q1.shown),"")}
这段表达式的“含义”是:如果问题代码为 q1 的问题不为空,则输出“- ”以及问题文本、“: ”和答案文本(join() 函数将多个元素连接为一个新字符串);否则不输出任何内容("" 表示空字符串)。
带子问题的问题
LimeSurvey 对以下所有问题类型使用子问题:
- 多短文本
- 多选题
- 带评论的多选题
- 阵列
- 阵列(5分制选择题)
- 阵列(10分制选择题)
- 阵列 (是/否/不确定)
- 阵列 (增加,不变,减少)
- 按列阵列
假设该问题的问题代码为 q2,子问题编号为 SQ001、SQ002 等(由 LimeSurvey 自动编号),我们可以使用以下方式引用问题文本和答案:
- {q2_SQ001.question}: {q2_SQ001.shown}
- {q2_SQ002.question}: {q2_SQ002.shown}
对于多选题,更合理的做法是不显示被勾选子问题的文本,而是为每个已选选项显示 Y:
- {q2_SQ001.question}: {q2_SQ001}
- {q2_SQ002.question}: {q2_SQ002}
...
请注意,目前无法输出带子问题的问题的问题文本,请参阅此功能请求。
示例 1(假设问题类型为多选题)
- 您知道这些汽车品牌吗?
-- Mercedes: Y
-- Audi: N
-- Volvo: Y
如果您只想输出已勾选的项目,可以在输出内容外加一个 IF 语句,并检查复选框的值:
{ if( q2_SQ001=="Y", join( "- ", q2_SQ001.question, ": ", q2_SQ001.shown ), "" ) }
如果您只想输出所选项目的列表,请使用 listifop 函数,例如:Mercedes, Volvo
{ listifop( 'value', '==', 'Y', 'question', ', ', that.q2.sgqa ) }
其中 that.q2 会展开为 q2 的所有子问题。更多详情请参见 self、this 和 that。
示例 2(假设问题类型为阵列(10分制选择题))
- 请对下列汽车品牌的质量进行评分,1=非常差,10=非常好?
-- Mercedes: 7
-- Audi: 9
-- Volvo: 9
如果您只想输出已评分的项目,可以在输出内容外加一个 IF 语句,并通过以下方式检查当前子问题是否已作答:
{ if( ! is_empty( q3_SQ001 ), join( "- ", q3_SQ001.question, ": ", q3_SQ001.shown ), "" ) }
例如,如果您只想输出所选项目中大于八的项目列表,请使用 listifop 函数,例如:Audi / Volvo
{ listifop( 'value', '>', 8, 'question', ' / ', that.q3.sgqa ) }
带有两个尺度的问题
假设使用了以下代码:
- 问题编码:q4
- 子问题代码:SQ001, SQ002, ...
- 尺度1的回复编号:A1, A2, ...
- 尺度2的回复编号:B1, B2, ...
引用第三个子问题、第二个尺度的答案示例:q4_SQ003_1 - 问题 4,子问题 3,第二个尺度。
让我们输出两个尺度以及前两个子问题的结果:
- {q4_SQ001_0.question}: {q4_SQ001_0.shown} / {q4_SQ001_1.shown}
- {q4_SQ002_0.question}: {q4_SQ002_0.shown} / {q4_SQ002_1.shown}
要输出子问题文本,您需要在占位符中添加尺度 ID(尽管两个尺度的文本相同)。因此,我们必须使用 {q4_SQ001_0.question} 或 {q4_SQ001_1.question},而不是 {q4_SQ001.question}。
如果您只想导出/显示至少有一个答案的子问题的结果,请对每个子问题使用以下语法:
{if(count(q4_SQ001_0,q4_SQ001_1)>0,join("- ",q4_SQ001_0.question,": ",q4_SQ001_0.shown," / ",q4_SQ001_1.shown),"")}
带有 X 和 Y 尺度的问题
这适用于所有允许对每个单元格作答的矩阵问题(而不是像前面所示那样仅对每一行作答):
- 阵列文本
- 阵列数字
假设使用以下代码:
- 问题代码:q5
- 子问题代码:SQ001、SQ002、...
- 答案代码:A1、A2、...
要引用某个子问题在某一列中的结果,您需要使用 QuestionCode . '_' . SubQuestionCode . '_' . AnswerCode。例如,引用第三个子问题、第二列的答案:q5_SQ003_A2。
我们来输出前两个子问题第 1-3 列的结果:
- {q5_SQ001_A1.question}: {q5_SQ001_A1.shown} | {q5_SQ001_A2.shown} | {q5_SQ001_A3.shown}
- {q5_SQ002_A1.question}: {q5_SQ002_A1.shown} | {q5_SQ002_A2.shown} | {q5_SQ002_A3.shown}
由于对于这些问题类型,每个单元格(X 轴和 Y 轴的组合)都对应一个答案选项,因此需要对每个单元格检查是否存在数据。示例:
{if(!is_empty(q5_SQ001_A1),join("- ",q5_SQ001_A1.question,": ",q5_SQ001_A1.shown),"")}
如果上一个问题的答案为空,则隐藏问题
| 目的 | 如果上一个问题的答案为空,则隐藏问题 |
| 类型 | 问题相关性 |
| 示例 | 问题一:问题代码 "name",问题文本 "What's your name?" 问题二:问题文本 "{name}, how old are you?" 任务:如果问题一的文本框为空,则隐藏问题二 |
| 表达式 | !is_empty(name) |
| 描述 | is_empty() 用于判断变量是否为空。"!" 对结果取反。因此,如果变量不为空,表达式为真,问题将被显示 |
| 步骤 | 创建/编辑问题二 在 "相关表达式" 中输入 "!is_empty(name)" |
| 示例文件 | Hide_question_if_empty_question_group.zip |
![]()
| |
如果上一个问题的答案为“是”或“否”,则隐藏题组
| 目的 | 如果上一个问题的答案为“是”或“否”,则隐藏题组 |
| 类型 | 题组相关性 |
| 示例 | 第一页,题组一,问题一:问题代码 "PET",问题文本 "Do you have a pet?" -Yes -No 第二页,题组二:标题 "About your pet(s)" 任务:根据问题一的答案为“是”/“否”来显示/隐藏题组二 |
| 表达式 | PET == "Y" |
| 描述 | PET 是您要检查其答案的问题的问题代码。如果不使用后缀,EM 将使用 "Qcode.code"。因此,您是将 PET 问题的答案代码与值 "Y" 进行比较。如果参与者回答“是”,则表达式为真,题组 "About your pet(s)" 将被显示。 |
| 步骤 | 创建/编辑题组二 在 "相关表达式" 中输入 "PET == "Y"" |
| 示例文件 | Hide_question group_if_answer_from_previous_question_is_Yes_or_No.zip |
![]()
| |
显示多答案输入问题字段的值
| 目的 | 显示多答案输入问题字段的值 |
| 类型 | 引用 |
| 示例 | 问题一:问题代码 "AskChildAge",问题文本 "How old are your children?"。子问题代码 -Child1 -Child2 -Child3 - ChildXXX 问题二:问题代码 "ReportChildAge",问题文本 "About your first child: - CHILD1 is AGE1." |
| 表达式 | {AskChildAge_Child1.question}, {AskChildAge_Child1.value} |
| 描述 | 您想在后续问题中使用某个子问题的值。您可以通过这种表达式访问子问题的值:QcodeQuestion_QcodeSubquestion.value |
| 步骤 | 创建/编辑第二个问题 在描述中输入以下文本:"About your first child: - {AskChildAge_Child1.question} is {AskChildAge_Child1.value}." |
| 示例文件 | Display_value_of_a_multiple_answer_input_question_field.zip |
| |
验证“阵列(数字)复选框”问题中每行勾选的框数
| 目的 | 验证每行勾选的框数 |
| 类型 | 验证 |
| 示例 | “阵列数字(复选框布局)”类型的问题 |
| 表达式 | sum(...) |
| 描述 | (sum(Test_A_1, Test_A_2, Test_A_3, Test_A_4, Test_A_5) <= X) 用于判断 A 行中是否至少勾选了 X 个复选框。 如果要检查全部三行(A、B、C),可以使用 "&&" 连接表达式: (sum(Test_A_1, Test_A_2, Test_A_3, Test_A_4, Test_A_5) <= X) && (sum(Test_B_1, Test_B_2, Test_B_3, Test_B_4, Test_B_5) <= X) && (sum(Test_C_1, Test_C_2, Test_C_3, Test_C_4, Test_C_5) <= X) |
| 步骤 | 创建/编辑“阵列数字(复选框布局)”类型的问题。 在高级问题设置的“问题验证等式”中输入上述表达式(您可能需要调整变量名称!)。 |
| 示例文件 | Validate number of boxes ticker per row for an Array (Numbers) Checkbox.lss |
![]()
| |
计算两个日期之间的差值
| 目的 | 计算两个日期之间的差值 |
| 类型 | 相关性 / 方程式问题类型 / 验证 |
| 示例 | 问题一(日期/时间,代码:DOB):您的出生日期是什么? 问题二(日期/时间,代码:datetoday):今天的日期是什么? 问题三(样板文本):您已出生 XXXX 天。 任务:计算并显示问题一与问题二所给日期之间相差的天数。 |
| 表达式 | {(strtotime(datetoday)-strtotime(DOB))/60/60/24} |
| 描述 | strtotime 计算 1970 年 1 月 1 日与给定日期之间的秒数。上述表达式计算两个给定日期之间的秒数。"/60/60/24" 部分则将秒数换算为天数。 除了询问 "datetoday" 之外,您也可以使用 strtotime('now') 或直接使用 time(),它会直接返回从 1970 年 1 月至今(即填写调查的时间)的秒数。因此,您可以使用方程式 {(time() - strtotime(DOB)) / 60 / 60 / 24 / 365.25} 快速算出一个人的年龄(以年为单位)。在上述任何情况下,日期都必须以正确的格式输入,否则 strtotime() 函数将无法正常工作。 |
| 步骤 | 创建两个日期问题(分别用于出生日期和今天的日期)以及一个样板文本问题。 在样板文本问题的问题文本中输入:"On {datetoday} you were {(strtotime(today)-strtotime(dob))/60/60/24} days days old." 请注意:strtotime 函数可以处理许多日期格式,但并非所有格式。如果遇到问题,请将调查的日期格式设置为 mm/dd/yyyy、yyyy-mm-dd 或 dd.mm.yyyy" |
| 示例文件 | Date_difference.zip |
| |
使用 ExpressionScript 进行评估
下面是另一个示例,介绍如何将 ExpressionScript 与阵列类型问题和评估结合使用:</ br>
假设您有 2 个阵列问题,并希望将计算结果数据保存到数据库中。这其实很简单,您需要创建并测试您的阵列,然后提交一份测试反馈,以查看其是否正常工作,并在完成页面中给出结果。
实施细节:
- 添加一个方程式类型的问题
- 添加以下一行,假设 Q1 是您的阵列问题代码,而 Q2 是第二个阵列问题代码:
{sum(Q1_SQ001.value,Q2_SQ001.value)}
请注意,SQ001 是任何子问题的默认代码。如果您更改了子问题代码,请相应地调整上面的方程式。
在阵列中使用 em_validation_q
您可以使用问题验证等式,通过任意条件来控制阵列。
实施细节:
- 对于第一个阵列:单项选择阵列
- 问题代码为 ARRAY
- 子问题代码为 SQ01、SQ02、SQ03 和 SQ04
- 更新整个问题验证等式,并输入
!is_empty(ARRAY_SQ01) and !is_empty(ARRAY_SQ03)
- 对于第二个阵列:文本阵列
- 问题代码为 ARRAYTEXT
- Y 轴上的子问题代码为 SY01、SY02、SY03 和 SY04
- 更新整个问题验证等式,并输入
count(self.sq_SY01 >= 1) and count(self.sq_SY03 >= 3)








