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

X++窗体开发中如何对选中客户的对应金额按客户ID分组求和

X++多客户选中记录金额汇总实现方案

问题场景

需要对窗体中选中的多条客户记录,按客户ID分组汇总对应金额,点击按钮打开新窗体后,在文本框中按如下格式展示汇总结果:

e006-M000021 总金额 = XXX,
e006-M000022 总金额 = XXX.

示例数据参考:
示例截图
原有代码仅能传递单条选中记录,无法实现多记录遍历、分组汇总逻辑,原有init方法代码如下:

public void init()
{    
   super();    
   if( element.args() && element.args().dataset() == tableNum(ARCSendSmsCustomerTmp))    
   {    
       Callertmp = element.args().record();    
   }    
   ////username and password are pulled from dealer parameters.    
   ARCDealerSmsParameters = ARCDealerSmsParameters::find();    
   ctrlUsername.text(ARCDealerSmsParameters.DealerUsername);    
   ctrlPassword.text(ARCDealerSmsParameters.DealerPassword);    
   ctrlSmsText.text(strFmt( @'SAYIN %1, %2 tarihi itibari ile toplam %3 TL gecikmiş ödemeniz bulunmaktadır.',Callertmp.CustName,Callertmp.DueDate,Callertmp.CurrencyAmount));    
   ctrlPhoneNumber.text(Callertmp.CustPhone);    
}

实现逻辑

核心问题是原有代码仅通过element.args().record()获取了单条选中记录,没有遍历调用方窗体所有选中行,也没有做按客户维度的分组聚合。
可直接通过调用方窗体引用,遍历选中的多行记录,用Map结构按客户ID累加金额,最后拼接成要求的文本格式即可,改动量最小。

步骤1:补充类声明变量

在被调用窗体的类声明中,新增如下变量:

ARCSendSmsCustomerTmp  selectedTmp;
Map                    customerAmountMap; // 键:客户ID,值:对应汇总金额
FormRun                callerForm;
FormDataSource         callerDs;
str                    smsDisplayText;

步骤2:替换原有init方法代码

public void init()
{
    super();
    // 加载经销商参数配置
    ARCDealerSmsParameters = ARCDealerSmsParameters::find();
    ctrlUsername.text(ARCDealerSmsParameters.DealerUsername);
    ctrlPassword.text(ARCDealerSmsParameters.DealerPassword);

    // 初始化汇总映射:字符串类型存客户ID,实数类型存累计金额
    customerAmountMap = new Map(Types::String, Types::Real);

    // 获取调用方窗体选中记录
    if (element.args() && element.args().caller())
    {
        callerForm = element.args().caller();
        // 注意:如果调用方窗体上ARCSendSmsCustomerTmp的数据源名称和表名不一致,替换为实际数据源名
        callerDs = callerForm.dataSource(tableNum(ARCSendSmsCustomerTmp));

        if (callerDs)
        {
            // 参数1代表遍历所有选中的记录
            for (selectedTmp = callerDs.getFirst(1); selectedTmp; selectedTmp = callerDs.getNext())
            {
                // 按客户ID累加金额:注意将CustAccount替换为你表中实际存储客户编号的字段名
                if (customerAmountMap.exists(selectedTmp.CustAccount))
                {
                    customerAmountMap.insert(
                        selectedTmp.CustAccount,
                        customerAmountMap.lookup(selectedTmp.CustAccount) + selectedTmp.CurrencyAmount
                    );
                }
                else
                {
                    customerAmountMap.insert(selectedTmp.CustAccount, selectedTmp.CurrencyAmount);
                }
            }
        }
    }

    // 拼接要求格式的展示文本
    MapEnumerator mapEnum = customerAmountMap.getEnumerator();
    while (mapEnum.moveNext())
    {
        smsDisplayText += strFmt(
            "%1 总金额 = %2,\n",
            mapEnum.currentKey(),
            num2Str(mapEnum.currentValue(), 0, 2, 0, 0) // 金额格式:保留2位小数,自动显示千分位
        );
    }
    // 处理末尾标点:把最后一行的逗号替换为句号
    if (strLen(smsDisplayText) > 0)
    {
        smsDisplayText = subStr(smsDisplayText, 1, strLen(smsDisplayText) - 2) + ".";
    }

    // 赋值到控件
    ctrlSmsText.text(smsDisplayText);
    // 取第一条选中记录的手机号填充控件,如有多手机号发送需求可自行扩展遍历逻辑
    if (selectedTmp)
    {
        ctrlPhoneNumber.text(selectedTmp.CustPhone);
    }
}

注意事项

  • 代码中CustAccount需替换为ARCSendSmsCustomerTmp表中实际存储客户编号(如e006-M000021)的字段名
  • 如果调用方窗体中临时表对应的数据源名称和表名不一致,需要将callerDs = callerForm.dataSource(tableNum(ARCSendSmsCustomerTmp))中的参数替换为实际数据源名
  • num2Str的参数可根据实际金额展示需求调整,当前配置为保留2位小数、自动添加千分位分隔符
  • 如果同一客户ID对应多个手机号/客户名称,可将Map的Value类型替换为结构体,同时存储金额、手机号、客户名等信息,适配更复杂的业务场景

内容的提问来源于stack exchange,提问作者Hakan Çelik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 19:39:37