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
相关产品推荐
相关产品推荐

