You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FreeMarker/NetSuite PDF模板:含空值的日期双重排序问题

FreeMarker实现多字段二级排序(含空值处理)

为什么你之前的写法无效

  • ?sort_by(['from_date', 'to_date']):FreeMarker的?sort_by只支持单个属性参数,不接受数组,因此这种写法语法错误,无法生效。
  • ?sort_by("from_date")?sort_by("to_date"):第二次sort_by会完全基于to_date重新排序,会打乱第一次from_date的排序结果,无法实现“先按from_date排序,再按to_date二次排序”的需求。

正确实现方式:使用?sort_with自定义比较逻辑

FreeMarker的?sort_with允许你自定义比较器函数,实现多字段的层级排序,同时可以灵活处理空值的排序位置。

方案1:精细控制空值排序位置(非空值优先)

<#list invoices?sort_with((a, b) -> {
    // 第一步:比较from_date
    if (a.from_date?has_content && b.from_date?has_content) {
        var fromCompare = a.from_date?compare_to(b.from_date);
        if (fromCompare != 0) {
            return fromCompare;
        }
        // from_date相等,第二步:比较to_date
        if (a.to_date?has_content && b.to_date?has_content) {
            return a.to_date?compare_to(b.to_date);
        } else if (a.to_date?has_content) {
            return -1; // 有to_date的记录排前面
        } else if (b.to_date?has_content) {
            return 1;
        }
        return 0;
    } else if (a.from_date?has_content) {
        return -1; // 有from_date的记录排前面
    } else if (b.from_date?has_content) {
        return 1;
    }
    // 两个from_date都为空,直接比较to_date
    if (a.to_date?has_content && b.to_date?has_content) {
        return a.to_date?compare_to(b.to_date);
    } else if (a.to_date?has_content) {
        return -1;
    } else if (b.to_date?has_content) {
        return 1;
    }
    return 0;
}) as inv>
    <!-- 表格行渲染逻辑 -->
    <tr>
        <td>${inv.from_date?string("yyyy-MM-dd")!""}</td>
        <td>${inv.to_date?string("yyyy-MM-dd")!""}</td>
        <!-- 其他列内容 -->
    </tr>
</#list>

方案2:简化空值处理(空值排最后)

如果希望所有空值(from_date或to_date为空)统一排到列表末尾,可以给空值设置一个极大的默认日期,简化比较逻辑:

<#list invoices?sort_with((a, b) -> {
    // 给空的from_date设置默认极大日期,让空值排最后
    var aFrom = a.from_date!new Date(9999, 11, 31);
    var bFrom = b.from_date!new Date(9999, 11, 31);
    var fromCompare = aFrom?compare_to(bFrom);
    
    if (fromCompare != 0) {
        return fromCompare;
    }
    
    // from_date相同,给空的to_date设置默认极大日期
    var aTo = a.to_date!new Date(9999, 11, 31);
    var bTo = b.to_date!new Date(9999, 11, 31);
    return aTo?compare_to(bTo);
}) as inv>
    <!-- 表格行渲染逻辑 -->
</#list>

关键说明

  • ?compare_to:FreeMarker日期类型的内置比较方法,返回值为-1(小于)、0(等于)、1(大于)。
  • ?has_content:判断字段是否非空(包括不为null、空字符串、空集合等)。
  • !:FreeMarker的默认值运算符,当字段为空时返回指定的默认值(方案2中用它给空日期设置极大值)。

内容的提问来源于stack exchange,提问作者Edgardo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 00:22:12