使用 ColdFusion (2016) 遍历电子表格数据并对输出进行分组
Using ColdFusion (2016) to loop over spreadsheet data and group the output
我提前为我的问题的长度道歉!我正在尝试自动为我们的活动构建论文时间表。论文和作者数据在电子表格中提供(我可怜的同事目前使用它逐行手动剪切和粘贴到 Word 文档中)。此电子表格包含我在 consistently-named 列中构建计划所需的所有信息,但可以按任何顺序排列。有点像这样(但真正的论文标题不会方便地编号):
Jack Doe - Co-Author - Penn State University - Aerodynamics - Aerodynamics Paper I
John Doe - Co-Author - Penn State University - Acoustics - Acoustics Paper I
John Smith - Co-Author - University of VA - Acoustics - Acoustics Paper I
Jane Doe - Main Author - Penn State University - Acoustics - Acoustics Paper I
Bob Smith - Main Author - GA Tech - Acoustics - Acoustics Paper II
Jack Smith - Main Author - University of MD - Acoustics - Acoustics Paper III
Jill Smith - Co-Author - University of MD - Acoustics - Acoustics Paper III
Bob Doe - Main Author - Penn State University - Aerodynamics - Aerodynamics Paper I
我的目标是转换电子表格数据,使论文按 session(即声学、空气动力学)分组和排序,然后按论文标题(即声学论文 I、声学论文 II)分组和排序,然后按每所大学的作者。问题是必须首先列出任何给定论文的 "main author",然后是来自同一学校的 co-authors(如果有),然后是来自其他大学的 co-authors。另一个 co-authors 可以按任何顺序排列,但也必须按大学分组。
所以拿原来的例子来说,应该是这样的:
ACOUSTICS
Acoustics Paper I
Jane Doe, John Doe, Penn State University; John Smith, University of VA
Acoustics Paper II
Bob Smith, GA Tech
Acoustics Paper III
Jack Smith, Jill Smith, University of MD
AERODYNAMICS
Aerodynamics Paper I
Bob Doe, Jack Doe, Penn State University
我快到了,但我只能到
ACOUSTICS
Acoustics Paper I
Jane Doe, Penn State University; John Doe, Penn State University; John Smith, University of VA;
Acoustics Paper II
Bob Smith, GA Tech;
Acoustics Paper III
Jack Smith, University of MD; Jill Smith, University of MD;
AERODYNAMICS
Aerodynamics Paper I
Bob Doe, Penn State University; Jack Doe, Penn State University;
我们正在使用 ACF 2016。我正在做的(我的代码在下面)是使用 cfspreadsheet 将电子表格读入查询 object。然后我将输出按 session 分组,然后按带有嵌套 cfoutputs 的标题分组。
然后,因为我想不出任何其他方法来识别每篇论文的主要作者并将他们放在第一位,所以我遍历该论文的所有作者并添加一个标志来识别他们,然后使用数组排序。请注意,我不能简单地按作者类型 DESC 排序,因为还有另一种类型,"presenting author,",为简洁起见,我省略了它 (ha)。有时主要作者也可以是主讲人,所以类型是 "main author presenting author."
无论如何,我然后循环遍历排序的数组。
以下是我目前尝试过的方法。我坚持让大学只为每个作者列表显示一次。我已经尝试在我的 authorArray 循环中放置另一个循环,但我不知道要索引或循环什么,所以它最终只是在每个作者姓名之后输出大学名称。我尝试过使用多维数组,甚至使用查询的查询来尝试构建一个漂亮的有序数据结构。但我显然做错了,因为我总是被按大学对作者分组所困扰。
我当然会很感激任何提示或提示!请注意,我无法更改最初使用此电子表格的要求。然而,一旦我得到它,我就可以使用我需要的信息做任何事情以获得所需的输出。所以我完全愿意做出任何改变或重新考虑我的整个方法。我下面的代码是我得到的最接近的代码。
非常感谢大家!这是我目前使用的:
<cfoutput query="queryPapers" group="PrimarySession">
#PrimarySession#
<cfoutput group="Title">
<p>#Title#</p>
<cfset authorArray = arrayNew(1)>
<cfoutput>
<cfset authorStruct = structNew()>
<cfset authorStruct.firstName = AuthorFirstName>
<cfset authorStruct.lastName = AuthorLastName>
<cfset authorStruct.institution = AuthorInstitution>
<cfset authorStruct.authorType = AuthorType>
<cfif findNoCase("Main", AuthorType)>
<cfset authorStruct.authorMain = "A">
<cfelse>
<cfset authorStruct.authorMain = "B">
</cfif>
<cfset arrayAppend(authorArray, authorStruct)>
<cfscript>
arraySort(
authorArray,
function (e1, e2) {
return compare(e1.authorMain, e2.authorMain);
}
);
</cfscript>
</cfoutput>
<cfloop index="i" from="1" to="#arrayLen(authorArray)#">
#authorArray[i].firstName# #authorArray[i].lastName#,
#authorArray[i].institution#;
</cfloop>
</cfoutput>
</cfoutput>
下面是上面代码的一些实际输出:
Dynamic Stall Investigations
Sergey Smith,* University of Maryland; Tobias Lersdorf, German University; Pascal Marceau, University of Maryland;
我正在努力
Dynamic Stall Investigations
Sergey Smith,* Pascal Marceau, University of Maryland; Tobias Lersdorf, German University
非常感谢阅读!
您的代码走在正确的轨道上,但我认为您有点过于复杂了。您可以使用下面的代码片段简化嵌套 <cfoutput>
处理。
<!--- Nested output loop for displaying required result --->
<cfoutput query="queryPapers" group="PrimarySession">
<strong>#Ucase(PrimarySession)#</strong><br />
<cfoutput group="Title">
<i>#Title#</i><br />
<cfoutput group="AuthorInstitution">
<cfoutput>
#AuthorFirstName# #AuthorLastName#,
</cfoutput>
#AuthorInstitution#; <!--- display institution once per group --->
</cfoutput>
<br /><br /> <!--- double-space after each title group --->
</cfoutput>
</cfoutput>
您遇到的只显示一次大学的问题可以通过添加另一层组嵌套并将其显示在额外嵌套组的页脚中来解决。
您在确保主要作者始终排在第一位方面遇到的问题应该在您的预处理中得到解决。为此,请使用您现有的 if/else 逻辑(主要作者为 "A",否则为 "B")并将其作为额外列添加到您的查询中。通过这种方式,您可以在输出循环之前的 order by
子句中使用它。
更新
所以我在发布我的第一次修订后意识到存在一个小的逻辑缺陷。它没有浮出水面的原因是因为在使用上面的示例数据时,主要作者方便地总是属于 "Title" 组中按字母顺序排在第一位的大学。在看到额外的示例输出后我意识到了这一点,我将这些行添加到我的代码示例中,它也错误地显示如下。
Dynamic Stall Investigations
Sergey Smith, University of Maryland; Tobias Lersdorf, German University; Pascal Marceau, University of Maryland;
解决方案是使用现有的 authorMain 列(A
用于主要作者,B
否则)并为属于 non-main 的作者添加另一个值 A2
与主要作者同一所大学。棘手的部分是您必须检查另一行中的值以确定何时设置 A2
。我能想到的最佳解决方案是在添加最初填充的 authorMain 列之后立即添加这两个代码块。
<!--- Sort query so "Main Author" is first within PrimarySession and Title --->
<cfquery name="queryPapers" dbtype="query">
select * from queryPapers
order by
PrimarySession,
Title,
AuthorMain
</cfquery>
<!--- Loop through above and update NON "Main-Author" rows "A2" if they have same University as "A" rows --->
<cfset MainInstitution = "">
<cfloop query="queryPapers">
<cfif queryPapers.authorMain eq "A">
<cfset MainInstitution = queryPapers.AuthorInstitution>
<cfelse>
<cfif MainInstitution eq queryPapers.AuthorInstitution>
<cfset QuerySetCell(queryPapers, "authorMain", "A2", queryPapers.currentRow)>
</cfif>
</cfif>
</cfloop>
首先按 PrimarySession、Title 和 AuthorMain 排序,然后循环遍历记录集并使用 A2
更新行(如果 non-main 作者与主要作者在同一所大学,通过使用MainInstitution
变量。此解决方案生成正确的结果,同时允许所有其他代码保持不变。
您可以看到我的第一个 revision and the second revision 模拟 OP 场景的代码之间的区别。
我提前为我的问题的长度道歉!我正在尝试自动为我们的活动构建论文时间表。论文和作者数据在电子表格中提供(我可怜的同事目前使用它逐行手动剪切和粘贴到 Word 文档中)。此电子表格包含我在 consistently-named 列中构建计划所需的所有信息,但可以按任何顺序排列。有点像这样(但真正的论文标题不会方便地编号):
Jack Doe - Co-Author - Penn State University - Aerodynamics - Aerodynamics Paper I
John Doe - Co-Author - Penn State University - Acoustics - Acoustics Paper I
John Smith - Co-Author - University of VA - Acoustics - Acoustics Paper I
Jane Doe - Main Author - Penn State University - Acoustics - Acoustics Paper I
Bob Smith - Main Author - GA Tech - Acoustics - Acoustics Paper II
Jack Smith - Main Author - University of MD - Acoustics - Acoustics Paper III
Jill Smith - Co-Author - University of MD - Acoustics - Acoustics Paper III
Bob Doe - Main Author - Penn State University - Aerodynamics - Aerodynamics Paper I
我的目标是转换电子表格数据,使论文按 session(即声学、空气动力学)分组和排序,然后按论文标题(即声学论文 I、声学论文 II)分组和排序,然后按每所大学的作者。问题是必须首先列出任何给定论文的 "main author",然后是来自同一学校的 co-authors(如果有),然后是来自其他大学的 co-authors。另一个 co-authors 可以按任何顺序排列,但也必须按大学分组。
所以拿原来的例子来说,应该是这样的:
ACOUSTICS
Acoustics Paper I
Jane Doe, John Doe, Penn State University; John Smith, University of VA
Acoustics Paper II
Bob Smith, GA Tech
Acoustics Paper III
Jack Smith, Jill Smith, University of MD
AERODYNAMICS
Aerodynamics Paper I
Bob Doe, Jack Doe, Penn State University
我快到了,但我只能到
ACOUSTICS
Acoustics Paper I
Jane Doe, Penn State University; John Doe, Penn State University; John Smith, University of VA;
Acoustics Paper II
Bob Smith, GA Tech;
Acoustics Paper III
Jack Smith, University of MD; Jill Smith, University of MD;
AERODYNAMICS
Aerodynamics Paper I
Bob Doe, Penn State University; Jack Doe, Penn State University;
我们正在使用 ACF 2016。我正在做的(我的代码在下面)是使用 cfspreadsheet 将电子表格读入查询 object。然后我将输出按 session 分组,然后按带有嵌套 cfoutputs 的标题分组。
然后,因为我想不出任何其他方法来识别每篇论文的主要作者并将他们放在第一位,所以我遍历该论文的所有作者并添加一个标志来识别他们,然后使用数组排序。请注意,我不能简单地按作者类型 DESC 排序,因为还有另一种类型,"presenting author,",为简洁起见,我省略了它 (ha)。有时主要作者也可以是主讲人,所以类型是 "main author presenting author."
无论如何,我然后循环遍历排序的数组。
以下是我目前尝试过的方法。我坚持让大学只为每个作者列表显示一次。我已经尝试在我的 authorArray 循环中放置另一个循环,但我不知道要索引或循环什么,所以它最终只是在每个作者姓名之后输出大学名称。我尝试过使用多维数组,甚至使用查询的查询来尝试构建一个漂亮的有序数据结构。但我显然做错了,因为我总是被按大学对作者分组所困扰。
我当然会很感激任何提示或提示!请注意,我无法更改最初使用此电子表格的要求。然而,一旦我得到它,我就可以使用我需要的信息做任何事情以获得所需的输出。所以我完全愿意做出任何改变或重新考虑我的整个方法。我下面的代码是我得到的最接近的代码。
非常感谢大家!这是我目前使用的:
<cfoutput query="queryPapers" group="PrimarySession">
#PrimarySession#
<cfoutput group="Title">
<p>#Title#</p>
<cfset authorArray = arrayNew(1)>
<cfoutput>
<cfset authorStruct = structNew()>
<cfset authorStruct.firstName = AuthorFirstName>
<cfset authorStruct.lastName = AuthorLastName>
<cfset authorStruct.institution = AuthorInstitution>
<cfset authorStruct.authorType = AuthorType>
<cfif findNoCase("Main", AuthorType)>
<cfset authorStruct.authorMain = "A">
<cfelse>
<cfset authorStruct.authorMain = "B">
</cfif>
<cfset arrayAppend(authorArray, authorStruct)>
<cfscript>
arraySort(
authorArray,
function (e1, e2) {
return compare(e1.authorMain, e2.authorMain);
}
);
</cfscript>
</cfoutput>
<cfloop index="i" from="1" to="#arrayLen(authorArray)#">
#authorArray[i].firstName# #authorArray[i].lastName#,
#authorArray[i].institution#;
</cfloop>
</cfoutput>
</cfoutput>
下面是上面代码的一些实际输出:
Dynamic Stall Investigations
Sergey Smith,* University of Maryland; Tobias Lersdorf, German University; Pascal Marceau, University of Maryland;
我正在努力
Dynamic Stall Investigations
Sergey Smith,* Pascal Marceau, University of Maryland; Tobias Lersdorf, German University
非常感谢阅读!
您的代码走在正确的轨道上,但我认为您有点过于复杂了。您可以使用下面的代码片段简化嵌套 <cfoutput>
处理。
<!--- Nested output loop for displaying required result --->
<cfoutput query="queryPapers" group="PrimarySession">
<strong>#Ucase(PrimarySession)#</strong><br />
<cfoutput group="Title">
<i>#Title#</i><br />
<cfoutput group="AuthorInstitution">
<cfoutput>
#AuthorFirstName# #AuthorLastName#,
</cfoutput>
#AuthorInstitution#; <!--- display institution once per group --->
</cfoutput>
<br /><br /> <!--- double-space after each title group --->
</cfoutput>
</cfoutput>
您遇到的只显示一次大学的问题可以通过添加另一层组嵌套并将其显示在额外嵌套组的页脚中来解决。
您在确保主要作者始终排在第一位方面遇到的问题应该在您的预处理中得到解决。为此,请使用您现有的 if/else 逻辑(主要作者为 "A",否则为 "B")并将其作为额外列添加到您的查询中。通过这种方式,您可以在输出循环之前的
order by
子句中使用它。
更新
所以我在发布我的第一次修订后意识到存在一个小的逻辑缺陷。它没有浮出水面的原因是因为在使用上面的示例数据时,主要作者方便地总是属于 "Title" 组中按字母顺序排在第一位的大学。在看到额外的示例输出后我意识到了这一点,我将这些行添加到我的代码示例中,它也错误地显示如下。
Dynamic Stall Investigations
Sergey Smith, University of Maryland; Tobias Lersdorf, German University; Pascal Marceau, University of Maryland;
解决方案是使用现有的 authorMain 列(A
用于主要作者,B
否则)并为属于 non-main 的作者添加另一个值 A2
与主要作者同一所大学。棘手的部分是您必须检查另一行中的值以确定何时设置 A2
。我能想到的最佳解决方案是在添加最初填充的 authorMain 列之后立即添加这两个代码块。
<!--- Sort query so "Main Author" is first within PrimarySession and Title --->
<cfquery name="queryPapers" dbtype="query">
select * from queryPapers
order by
PrimarySession,
Title,
AuthorMain
</cfquery>
<!--- Loop through above and update NON "Main-Author" rows "A2" if they have same University as "A" rows --->
<cfset MainInstitution = "">
<cfloop query="queryPapers">
<cfif queryPapers.authorMain eq "A">
<cfset MainInstitution = queryPapers.AuthorInstitution>
<cfelse>
<cfif MainInstitution eq queryPapers.AuthorInstitution>
<cfset QuerySetCell(queryPapers, "authorMain", "A2", queryPapers.currentRow)>
</cfif>
</cfif>
</cfloop>
首先按 PrimarySession、Title 和 AuthorMain 排序,然后循环遍历记录集并使用 A2
更新行(如果 non-main 作者与主要作者在同一所大学,通过使用MainInstitution
变量。此解决方案生成正确的结果,同时允许所有其他代码保持不变。
您可以看到我的第一个 revision and the second revision 模拟 OP 场景的代码之间的区别。