报表csv导出3
This commit is contained in:
wenlukang1 2025-07-29 17:00:48 +08:00
parent bbb8917039
commit 7e8eb690cb
2 changed files with 115 additions and 26 deletions

View File

@ -1,4 +1,4 @@
package shkd.sys.sys.plugin.report.util;
package shkd.sys.sys.plugin.report;
import dm.jdbc.util.StringUtil;
import kd.bos.cache.CacheFactory;
@ -7,12 +7,17 @@ import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.metadata.IMetadata;
import kd.bos.dataentity.metadata.clr.DataEntityPropertyCollection;
import kd.bos.entity.MainEntityType;
import kd.bos.entity.NumberFormatProvider;
import kd.bos.entity.datamodel.FmtField;
import kd.bos.entity.report.AbstractReportColumn;
import kd.bos.entity.report.IReportListModel;
import kd.bos.entity.report.ReportColumn;
import kd.bos.form.control.Toolbar;
import kd.bos.form.control.events.ItemClickEvent;
import kd.bos.report.ReportList;
import kd.bos.report.plugin.AbstractReportFormPlugin;
import org.apache.commons.io.FileUtils;
import kd.bos.report.proxy.ReportListProxy;
import shkd.sys.sys.plugin.report.util.CsvExportUtil;
import java.io.IOException;
import java.nio.file.Files;
@ -22,9 +27,10 @@ import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class ExportCSV extends AbstractReportFormPlugin {
import static shkd.sys.sys.plugin.report.util.ReportUtils.processFieldValue;
public class ExportCSVReportFormPlugin extends AbstractReportFormPlugin {
@Override
public void registerListener(EventObject e) {
@ -34,45 +40,69 @@ public class ExportCSV extends AbstractReportFormPlugin {
// 监听工具栏这个按钮的点击事件
export.addItemClickListener(this);
export.addClickListener(this);
}
/**
* 处理列表项点击事件当点击的项为 "shkd_exportcsv" 执行导出 CSV 文件的操作
*
* @param evt 列表项点击事件对象包含被点击项的相关信息
*/
@Override
public void itemClick(ItemClickEvent evt) {
super.itemClick(evt);
String itemKey = evt.getItemKey();
if (StringUtil.equals("shkd_exportcsv", itemKey)) {
// 获取数据实体类型及其属性集合
MainEntityType dataEntityType = this.getModel().getDataEntityType();
DataEntityPropertyCollection properties = dataEntityType.getProperties();
String reportName = dataEntityType.getDisplayName().getLocaleValue();
List<String> keyHeaders = properties.stream()
.filter(Objects::nonNull)
.map(IMetadata::getName)
.collect(Collectors.toList());
List<String> headers = properties.stream()
.filter(Objects::nonNull)
.filter(o -> Objects.nonNull(o.getDisplayName()))
.map(o -> o.getDisplayName().getLocaleValue())
// 获取报表列表控件及模型并取得行数和列信息
ReportList reportList = this.getControl("reportlistap");
IReportListModel reportListModel = reportList.getReportModel();
int rowCount = reportListModel.getRowCount();
ReportListProxy reportListProxy = new ReportListProxy(reportList);
List<AbstractReportColumn> columns = reportListProxy.getColumnList(reportListModel);
List<ReportColumn> cols = reportListProxy.getReportColumnList(columns, true);
// 获取所有行数据并初始化数字格式化提供器
DynamicObjectCollection rowData = reportListModel.getRowData(0, rowCount, false);
NumberFormatProvider numberFormatProvider = ReportColumn.initNumberFormatProvider(rowData, cols);
// 提取需要导出的字段名排除 fseq 字段
List<String> headerKeys = numberFormatProvider.getFmtFields().stream()
.filter(o -> !Objects.equals(o.getFieldName(), "fseq"))
.map(FmtField::getFieldName)
.collect(Collectors.toList());
String timestamp = LocalDateTime.now()
.format(DateTimeFormatter.ofPattern("yyyyMMddHHmm"));
// 构建属性名到显示名称的映射表便于快速查找
Map<String, String> nameToDisplay =
properties.stream()
.filter(Objects::nonNull)
.filter(p -> p.getDisplayName() != null)
.collect(Collectors.toMap(
IMetadata::getName,
p -> p.getDisplayName().getLocaleValue(),
(v1, v2) -> v1));
int random = ThreadLocalRandom.current().nextInt(100, 1000); // 3 位随机数
String reportNameExt = timestamp + random;
IReportListModel reportList = ((ReportList) this.getControl("reportlistap")).getReportModel();
int rowCount = reportList.getRowCount();
DynamicObjectCollection rowData = reportList.getRowData(0, rowCount, false);
// 按照字段顺序获取对应的显示名称缺失则使用空字符串
List<String> headers = headerKeys.stream()
.map(k -> nameToDisplay.getOrDefault(k, ""))
.collect(Collectors.toList());
// 构造每一行的数据列表处理复杂对象的name属性及本地化
List<List<?>> rows2 = rowData.stream()
.map(obj -> keyHeaders.stream()
.map(obj::get) // 使用 DynamicObject get 方法获取属性值
.map(obj -> headerKeys.stream()
.map(key -> processFieldValue(obj.get(key)))
.collect(Collectors.toList()))
.collect(Collectors.toList());
// 生成时间戳和随机数作为文件名的一部分
String timestamp = LocalDateTime.now()
.format(DateTimeFormatter.ofPattern("yyyyMMddHHmm"));
int random = ThreadLocalRandom.current().nextInt(100, 1000); // 3 位随机数
String reportNameExt = timestamp + random;
try {
// 定义本地测试目录和完整文件路径
@ -84,8 +114,8 @@ public class ExportCSV extends AbstractReportFormPlugin {
//
// Path tempFile = dirPath.resolve(reportName + reportNameExt + ".csv");
// CsvExportUtil.writeCsvToFile(tempFile, headers, rows2);
//
// // 打印文件路径用于本地验证
// 打印文件路径用于本地验证
// System.out.println("CSV 文件已保存至: " + tempFile.toAbsolutePath());
Path tempFile = Files.createTempFile(reportName + reportNameExt, ".csv");

View File

@ -49,4 +49,63 @@ public class ReportUtils {
}
return filters;
}
/**
* 处理字段值支持简单值和复杂对象如含name属性的对象
*
* @param value 原始字段值
* @return 处理后的字符串值
*/
public static Object processFieldValue(Object value) {
if (value == null) {
return "";
}
// 如果是DynamicObject或类似结构尝试获取name属性
try {
// 尝试调用get("name")方法获取name属性
Object nameValue = value.getClass().getMethod("get", String.class).invoke(value, "name");
if (nameValue != null) {
// 如果name是一个本地化对象则进一步处理
return processLocalizedValue(nameValue);
}
// 如果没有name属性直接返回原值的toString()
return value.toString();
} catch (Exception e) {
// 如果调用失败说明不是复杂对象直接返回toString()
return value.toString();
}
}
/**
* 处理本地化值对象优先获取ZH_TW其次ZH_CN
*
* @param localizedObj 本地化对象
* @return 对应语言的值
*/
public static String processLocalizedValue(Object localizedObj) {
if (localizedObj == null) {
return "";
}
try {
// 尝试获取ZH_CN本地化值
Object zhCnValue = localizedObj.getClass().getMethod("get", String.class).invoke(localizedObj, "zh_CN");
if (zhCnValue != null) {
return zhCnValue.toString();
}
// // 尝试获取ZH_TW本地化值
// Object zhTwValue = localizedObj.getClass().getMethod("get", String.class).invoke(localizedObj, "zh_TW");
// if (zhTwValue != null) {
// return zhTwValue.toString();
// }
// 都没有则返回默认toString()
return localizedObj.toString();
} catch (Exception e) {
// 异常情况下返回toString()
return localizedObj.toString();
}
}
}