最优分案算法:
在开发中,有这么一种业务场景,就是需要根据一定的比例,按照数量与金额都按照这个比例进行分配,要求数量与金额都能达到最优的情况。如果只按照数量或者金额分配是比较好计算的,但是两者都需要兼顾到,这是一种比较复杂的算法,我现在将我的算法demo贴出来,供同学们一起学习一下。
可以直接将代码拷贝到本地,main方法直接运行
package cn.com.smart.eq.test;
import java.awt.*;
public class CaseAssignTool {
public CaseAssignTool() {
}
public static void main(String[] args) {
CaseFrame frame = new CaseFrame();
frame.setTitle("手工分案-V2.8");
frame.setDefaultCloseOperation(3);
frame.setLocationRelativeTo((Component)null);
frame.setVisible(true);
frame.setResizable(false);
}
}
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package cn.com.smart.eq.test;
import com.zpp.dto.AssignDto;
import com.zpp.dto.CaseDto;
import java.awt.Font;
import java.awt.LayoutManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
class CaseFrame extends JFrame {
private static final long serialVersionUID = -4289784953416095500L;
private Font font = new Font("微软雅黑", 0, 18);
private int hd = 30;
private JTextField fileText;
private JTextField percentText;
private JButton assign;
private JButton select;
private JButton clean;
private JScrollPane scroll;
private JTextArea area;
private JRadioButton autoOpen;
private JComboBox<Integer> minBox;
String filePath = "/Users/candy/Desktop/aa.xlsx";
String percent = "1,2,3,4";
Integer[] arr = new Integer[]{200, 300, 400, 500, 1000};
public CaseFrame() {
this.setSize(645, 430);
this.getContentPane().setLayout((LayoutManager)null);
int yy = 10;
this.add(this.setLabel(yy, 20, 110, "分案文件"), (Object)null);
this.add(this.setFileText(yy, 105, 410, this.filePath), (Object)null);
this.add(this.setSelectButton(yy, 530, 90, "选择", new SelectListener((SelectListener)null)), (Object)null);
yy = 45;
this.add(this.setLabel(yy, 20, 110, "对象占比"), (Object)null);
this.add(this.setPercentText(yy, 105, 180, this.percent), (Object)null);
this.add(this.setMinBox(yy, 295, 75, this.arr), (Object)null);
this.add(this.setCleanButton(yy, 380, 71, "清空", new CleanListener((CleanListener)null)), (Object)null);
this.add(this.setOpenRadio(yy, 455, 71, "打开", false), (Object)null);
this.add(this.setAssignButton(yy, 530, 90, "分配", new AssignListener((AssignListener)null)), (Object)null);
this.add(this.setArea(20, 80, 600, 300, true), (Object)null);
this.add(this.setScroll(20, 80, 600, 300, this.area), (Object)null);
}
private JLabel setLabel(int y, int x, int w, String text) {
JLabel label = new JLabel(text);
label.setBounds(x, y, w, this.hd);
label.setFont(this.font);
return label;
}
private JTextField setFileText(int y, int x, int w, String text) {
if (this.fileText == null) {
this.fileText = new JTextField(text);
}
this.fileText.setBounds(x, y, w, this.hd);
this.fileText.setFont(this.font);
return this.fileText;
}
private JTextField setPercentText(int y, int x, int w, String text) {
if (this.percentText == null) {
this.percentText = new JTextField(text);
}
this.percentText.setBounds(x, y, w, this.hd);
this.percentText.setFont(this.font);
return this.percentText;
}
private JComboBox<Integer> setMinBox(int y, int x, int w, Integer[] arr) {
if (this.minBox == null) {
this.minBox = new JComboBox();
}
this.minBox.setBounds(x, y, w, this.hd);
this.minBox.setFont(this.font);
Integer[] var8 = arr;
int var7 = arr.length;
for(int var6 = 0; var6 < var7; ++var6) {
Integer item = var8[var6];
this.minBox.addItem(item);
}
return this.minBox;
}
private JRadioButton setOpenRadio(int y, int x, int w, String text, boolean select) {
if (this.autoOpen == null) {
this.autoOpen = new JRadioButton(text);
}
this.autoOpen.setBounds(x, y, w, this.hd);
this.autoOpen.setFont(this.font);
this.autoOpen.setSelected(select);
return this.autoOpen;
}
private JButton setSelectButton(int y, int x, int w, String text, SelectListener actionListener) {
if (this.select == null) {
this.select = new JButton(text);
}
this.select.setBounds(x, y, w, this.hd);
this.select.setFont(this.font);
this.select.addActionListener(actionListener);
return this.select;
}
private JButton setCleanButton(int y, int x, int w, String text, CleanListener actionListener) {
if (this.clean == null) {
this.clean = new JButton(text);
}
this.clean.setBounds(x, y, w, this.hd);
this.clean.setFont(this.font);
this.clean.addActionListener(actionListener);
return this.clean;
}
private JButton setAssignButton(int y, int x, int w, String text, AssignListener actionListener) {
if (this.assign == null) {
this.assign = new JButton(text);
}
this.assign.setBounds(x, y, w, this.hd);
this.assign.setFont(this.font);
this.assign.addActionListener(actionListener);
return this.assign;
}
private JTextArea setArea(int x, int y, int w, int h, boolean scroll) {
if (this.area == null) {
this.area = new JTextArea();
}
this.area.setBounds(x, y, w, h);
this.area.setAutoscrolls(scroll);
this.area.setFont(this.font);
return this.area;
}
private JScrollPane setScroll(int x, int y, int w, int h, JTextArea area) {
if (this.scroll == null) {
this.scroll = new JScrollPane();
}
this.scroll.setBounds(x, y, w, h);
this.scroll.setViewportView(area);
return this.scroll;
}
private class AssignListener implements ActionListener {
private AssignListener(AssignListener assignListener) {
}
public void actionPerformed(ActionEvent e) {
String perStr = CaseFrame.this.percentText.getText();
if (!this.regex(perStr.trim(), "\\d+(\\.\\d+)?(\\s*,\\s*\\d+(\\.\\d+)?)*")) {
this.append("【分配对象】值有误");
} else {
String path = CaseFrame.this.fileText.getText();
if (path != null && !"".equals(path.trim())) {
File file = new File(path);
if (!file.exists()) {
this.append("【分案文件】不存在");
} else {
long fileSize = file.length();
this.append("文件大小=" + String.format("%.3f", (double)(fileSize / 1024L) / 1024.0) + "MB");
Workbook book = this.excel2book(file);
if (book == null) {
this.append("创建【Workbook】为空");
} else {
Sheet sheet = book.getSheetAt(0);
int rowNum = sheet.getLastRowNum();
this.append("总行数=" + (rowNum + 1));
List<String> headList = this.row2list(sheet.getRow(0));
List<String> mustHeads = Arrays.asList("案件号", "逾期金额");
Iterator var13 = mustHeads.iterator();
while(var13.hasNext()) {
String mustHead = (String)var13.next();
if (!headList.contains(mustHead)) {
this.append("表头必须包含【" + mustHead + "】字段");
return;
}
}
List<CaseDto> caseList = new ArrayList<>();
this.sheet2list(caseList, sheet, rowNum, headList);
if (caseList.isEmpty()) {
this.append("【生成case】为空");
} else {
int max = caseList.size();
Map<AssignDto, List<CaseDto>> result = this.assign(caseList, perStr, max);
Iterator var16 = result.entrySet().iterator();
while(var16.hasNext()) {
Map.Entry<AssignDto, List<CaseDto>> entry = (Map.Entry)var16.next();
((AssignDto)entry.getKey()).setRealAmt(entry.getValue().stream().map(CaseDto::getAmtBal).reduce(BigDecimal.ZERO, BigDecimal::add));
((AssignDto)entry.getKey()).setRealNum(((List)entry.getValue()).size());
}
List<AssignDto> dtos = (List)result.keySet().stream().sorted(Comparator.comparing(AssignDto::getOffset)).collect(Collectors.toList());
this.printList("实际结果", dtos, true);
this.data2excel(result, path);
}
}
}
} else {
this.append("【分案文件】值为空");
}
}
}
private Workbook excel2book(File file) {
InputStream fis = null;
try {
fis = new FileInputStream(file);
} catch (Exception var15) {
this.append("创建【InputStream】失败");
}
Workbook book = null;
try {
book = WorkbookFactory.create(fis);
} catch (Exception var14) {
this.append("创建【Workbook】失败");
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException var13) {
this.append("关闭【InputStream】失败");
}
}
}
return book;
}
private void sheet2list(List<CaseDto> caseList, Sheet sheet, int rowNum, List<String> headList) {
int size = headList.size();
for(int i = 1; i <= rowNum; ++i) {
Row row = sheet.getRow(i);
if (row == null) {
this.append("【空行】第" + (i + 1) + "行");
return;
}
CaseDto dto = new CaseDto();
for(int j = 0; j < size; ++j) {
Cell cell = row.getCell(j);
String cellVal = null;
String var12;
switch ((var12 = (String)headList.get(j)).hashCode()) {
case 26302985:
if (!var12.equals("案件号")) {
return;
}
cellVal = this.cell2string(cell, true);
if (StringUtils.isBlank(cellVal)) {
this.append("第" + (i + 1) + "行【" + (String)headList.get(j) + "】为空");
return;
}
dto.setCaseId(Long.valueOf(cellVal));
break;
case 1126628173:
if (var12.equals("逾期金额")) {
cellVal = this.cell2string(cell, true);
if (StringUtils.isBlank(cellVal)) {
this.append("第" + (i + 1) + "行【" + (String)headList.get(j) + "】为空");
return;
}
dto.setAmtBal(new BigDecimal(cellVal));
break;
}
return;
default:
return;
}
}
caseList.add(dto);
}
}
private Map<AssignDto, List<CaseDto>> assign(List<CaseDto> caseList, String percentStr, int max) {
BigDecimal totalAmt = (BigDecimal)caseList.stream().map(CaseDto::getAmtBal).reduce(BigDecimal.ZERO, BigDecimal::add);
List<AssignDto> userList = this.buildAssignDto(percentStr, caseList.size(), totalAmt, max);
this.printAssignDto(userList);
long start = System.currentTimeMillis();
this.append("\n<< 分案开始 >>");
Map<AssignDto, List<CaseDto>> userMap = this.oneStep(caseList, userList, totalAmt.multiply(new BigDecimal("0.0001")), max / 2);
Map<AssignDto, List<CaseDto>> map = this.fixResult(userMap);
long end = System.currentTimeMillis();
this.append("\n<< 分案完成 >> 耗时:" + (double)(end - start) / 1000.0 + "s");
return map;
}
private void printAssignDto(List<AssignDto> userList) {
Map<String, List<AssignDto>> keyUser = new HashMap();
AssignDto curr;
String userId;
for(Iterator var4 = userList.iterator(); var4.hasNext(); ((List)keyUser.get(userId)).add(curr)) {
curr = (AssignDto)var4.next();
userId = curr.getUserId().split("_", 2)[0];
if (!keyUser.containsKey(userId)) {
keyUser.put(userId, new ArrayList());
}
}
List<AssignDto> result = new ArrayList();
Iterator var11 = keyUser.entrySet().iterator();
while(var11.hasNext()) {
Map.Entry<String, List<AssignDto>> entry = (Map.Entry)var11.next();
AssignDto dto = new AssignDto((String)entry.getKey(), BigDecimal.ZERO);
Iterator var8 = ((List)entry.getValue()).iterator();
while(var8.hasNext()) {
AssignDto currx = (AssignDto)var8.next();
dto.setPercent(currx.getPercent());
dto.setAssignNum(dto.getAssignNum() + currx.getAssignNum());
dto.setAssignAmt(dto.getAssignAmt().add(currx.getAssignAmt()));
dto.setRealNum(dto.getRealNum() + currx.getRealNum());
dto.setRealAmt(dto.getRealAmt().add(currx.getRealAmt()));
}
result.add(dto);
}
this.printList("分配汇总", result, true);
}
private List<AssignDto> buildAssignDto(String percentStr, int caseSize, BigDecimal totalAmt, int max) {
BigDecimal caseNum = BigDecimal.valueOf((long)caseSize);
BigDecimal avgAmt = totalAmt.divide(caseNum, 2, 4);
this.append("案件总数=" + caseSize + ",案件总金额=" + totalAmt + ",平均金额=" + avgAmt);
BigDecimal totalPercent = BigDecimal.ZERO;
List<BigDecimal> percents = new ArrayList();
String[] str = percentStr.trim().split("\\s*,\\s*");
int len;
int size;
if (str.length == 1) {
len = (int)Double.parseDouble(str[0]);
for(size = 1; size <= len; ++size) {
percents.add(BigDecimal.ONE);
}
totalPercent = BigDecimal.valueOf((long)len);
} else {
for(len = 0; len < str.length; ++len) {
BigDecimal curr = new BigDecimal(str[len]);
if (curr.compareTo(BigDecimal.ZERO) > 0) {
percents.add(curr);
totalPercent = totalPercent.add(curr);
}
}
}
Collections.sort(percents);
List<AssignDto> dtos = new ArrayList();
size = percents.size();
BigDecimal passAmt = BigDecimal.ZERO;
int passNum = 0;
int left;
for(int i = 0; i < size - 1; ++i) {
String userIdx = "U" + (i + 1) + "_";
BigDecimal px = (BigDecimal)percents.get(i);
int assignNumx = caseNum.multiply(px).divide(totalPercent, 2, 1).intValue();
BigDecimal assignAmtx = totalAmt.multiply(px).divide(totalPercent, 2, 4);
left = assignNumx / max;
int leftx = assignNumx % max;
BigDecimal passx;
int j;
BigDecimal amt;
AssignDto d;
AssignDto dx;
if (leftx > 0) {
passx = BigDecimal.ZERO;
for(j = 0; j < left; ++j) {
amt = assignAmtx.multiply(BigDecimal.valueOf((long)max)).divide(BigDecimal.valueOf((long)assignNumx), 2, 4);
d = new AssignDto(userIdx + j, px);
d.setAssignNum(max);
d.setAssignAmt(amt);
dtos.add(d);
passx = passx.add(amt);
}
dx = new AssignDto(userIdx + left, px);
dx.setAssignNum(leftx);
dx.setAssignAmt(assignAmtx.subtract(passx));
dtos.add(dx);
} else {
passx = BigDecimal.ZERO;
for(j = 0; j < left - 1; ++j) {
amt = assignAmtx.multiply(BigDecimal.valueOf((long)max)).divide(BigDecimal.valueOf((long)assignNumx), 2, 4);
d = new AssignDto(userIdx + j, px);
d.setAssignNum(max);
d.setAssignAmt(amt);
dtos.add(d);
passx = passx.add(amt);
}
dx = new AssignDto(userIdx + (left - 1), px);
dx.setAssignNum(leftx);
dx.setAssignAmt(assignAmtx.subtract(passx));
dtos.add(dx);
}
passAmt = passAmt.add(assignAmtx);
passNum += assignNumx;
}
if (passNum < caseSize) {
String userId = "U" + size + "_";
BigDecimal p = (BigDecimal)percents.get(size - 1);
int assignNum = caseSize - passNum;
BigDecimal assignAmt = totalAmt.subtract(passAmt);
int time = assignNum / max;
left = assignNum % max;
BigDecimal pass;
int jx;
AssignDto dxx;
AssignDto dxxx;
BigDecimal amtx;
if (left > 0) {
pass = BigDecimal.ZERO;
for(jx = 0; jx < time; ++jx) {
amtx = assignAmt.multiply(BigDecimal.valueOf((long)max)).divide(BigDecimal.valueOf((long)assignNum), 2, 4);
dxxx = new AssignDto(userId + jx, p);
dxxx.setAssignNum(max);
dxxx.setAssignAmt(amtx);
dtos.add(dxxx);
pass = pass.add(amtx);
}
dxx = new AssignDto(userId + time, p);
dxx.setAssignNum(left);
dxx.setAssignAmt(assignAmt.subtract(pass));
dtos.add(dxx);
} else {
pass = BigDecimal.ZERO;
for(jx = 0; jx < time - 1; ++jx) {
amtx = assignAmt.multiply(BigDecimal.valueOf((long)max)).divide(BigDecimal.valueOf((long)assignNum), 2, 4);
dxxx = new AssignDto(userId + jx, p);
dxxx.setAssignNum(max);
dxxx.setAssignAmt(amtx);
dtos.add(dxxx);
pass = pass.add(amtx);
}
dxx = new AssignDto(userId + (time - 1), p);
dxx.setAssignNum(left);
dxx.setAssignAmt(assignAmt.subtract(pass));
dtos.add(dxx);
}
}
List<AssignDto> dtosx = (List)dtos.stream().filter((u) -> {
return u.getAssignNum() > 0;
}).collect(Collectors.toList());
dtosx.sort(Comparator.comparing(AssignDto::getAssignNum));
return dtosx;
}
private Map<AssignDto, List<CaseDto>> fixResult(Map<AssignDto, List<CaseDto>> map) {
Map<String, List<AssignDto>> keyUser = new HashMap();
Map<String, List<CaseDto>> keyCase = new HashMap();
Map.Entry entryx;
String userId;
for(Iterator var5 = map.entrySet().iterator(); var5.hasNext(); ((List)keyCase.get(userId)).addAll((Collection)entryx.getValue())) {
entryx = (Map.Entry)var5.next();
AssignDto curr = (AssignDto)entryx.getKey();
userId = curr.getUserId().split("_", 2)[0];
if (!keyUser.containsKey(userId)) {
keyUser.put(userId, new ArrayList());
}
((List)keyUser.get(userId)).add((AssignDto)entryx.getKey());
if (!keyCase.containsKey(userId)) {
keyCase.put(userId, new ArrayList());
}
}
Map<AssignDto, List<CaseDto>> result = new HashMap();
Iterator var12 = keyUser.entrySet().iterator();
while(var12.hasNext()) {
Map.Entry<String, List<AssignDto>> entry = (Map.Entry)var12.next();
AssignDto dto = new AssignDto((String)entry.getKey(), BigDecimal.ZERO);
Iterator var9 = ((List)entry.getValue()).iterator();
while(var9.hasNext()) {
AssignDto currx = (AssignDto)var9.next();
dto.setPercent(currx.getPercent());
dto.setAssignNum(dto.getAssignNum() + currx.getAssignNum());
dto.setAssignAmt(dto.getAssignAmt().add(currx.getAssignAmt()));
dto.setRealNum(dto.getRealNum() + currx.getRealNum());
dto.setRealAmt(dto.getRealAmt().add(currx.getRealAmt()));
}
result.put(dto, (List)keyCase.get(entry.getKey()));
}
return result;
}
private Map<AssignDto, List<CaseDto>> oneStep(List<CaseDto> caseList, List<AssignDto> userList, BigDecimal maxOffset, int maxTimes) {
this.append("\n最大偏差仅=" + maxOffset + ",最大微调次数=" + maxTimes);
Map<AssignDto, List<CaseDto>> map = new HashMap<>();
List<CaseDto> left = caseList;
int usize = userList.size();
for(int x = 0; x < usize - 1; ++x) {
int size = ((List<?>)left).size();
int num = ((AssignDto)userList.get(x)).getAssignNum();
int mod = size / num;
List<CaseDto> curr = new ArrayList<>();
List<CaseDto> temp = new ArrayList<>();
for(int j = 0; j < size; ++j) {
if (j % mod == (j / mod % 2 == 0 ? 0 : mod - 1) && curr.size() < num) {
curr.add((CaseDto)((List<?>)left).get(j));
} else {
temp.add((CaseDto)((List<?>)left).get(j));
}
}
((AssignDto)userList.get(x)).setRealAmt((BigDecimal)curr.stream().map(CaseDto::getAmtBal).reduce(BigDecimal.ZERO, BigDecimal::add));
BigDecimal offset = ((AssignDto)userList.get(x)).getOffset();
int currSize = curr.size();
int leftSize = temp.size();
int times = 1;
for(String flag = ((AssignDto)userList.get(x)).getUserId() + ":0"; offset.abs().compareTo(maxOffset) > 0 && times < maxTimes; ++times) {
BigDecimal lastSub = offset.abs();
String lastFlag = flag;
int[] idx = new int[]{currSize - 1, leftSize - 1};
BigDecimal currSub;
for(int k = 0; k < currSize; ++k) {
for(int m = 0; m < leftSize; ++m) {
currSub = ((CaseDto)temp.get(m)).getAmtBal().subtract(((CaseDto)curr.get(k)).getAmtBal()).add(offset).abs();
if (currSub.compareTo(lastSub) < 0) {
idx[0] = k;
idx[1] = m;
lastSub = currSub;
lastFlag = ((AssignDto)userList.get(x)).getUserId() + ":" + k;
}
}
}
if (offset.abs().compareTo(lastSub) == 0 && flag.equals(lastFlag)) {
this.append((times == 1 ? "\n" : "") + "【" + ((AssignDto)userList.get(x)).getUserId() + "】第" + times + "次:已最优,跳出循环");
break;
}
this.append((times == 1 ? "\n" : "") + "【" + ((AssignDto)userList.get(x)).getUserId() + "】第" + times + "次:调前=" + offset + ",调后=" + lastSub + ",交换[ " + idx[0] + " <> " + idx[1] + " ]");
CaseDto c1 = (CaseDto)curr.get(idx[0]);
CaseDto c2 = (CaseDto)temp.get(idx[1]);
curr.remove(idx[0]);
temp.remove(idx[1]);
curr.add(c2);
temp.add(c1);
currSub = c2.getAmtBal().subtract(c1.getAmtBal());
((AssignDto)userList.get(x)).setRealAmt(((AssignDto)userList.get(x)).getRealAmt().add(currSub));
offset = ((AssignDto)userList.get(x)).getOffset();
}
left = temp;
((AssignDto)userList.get(x)).setRealNum(curr.size());
map.put((AssignDto)userList.get(x), curr);
}
((AssignDto)userList.get(usize - 1)).setRealAmt(left.stream().map(CaseDto::getAmtBal).reduce(BigDecimal.ZERO, BigDecimal::add));
((AssignDto)userList.get(usize - 1)).setRealNum(((List)left).size());
map.put((AssignDto)userList.get(usize - 1), left);
return map;
}
private void data2excel(Map<AssignDto, List<CaseDto>> result, String path) {
Workbook book = new SXSSFWorkbook(64);
Sheet sheet = book.createSheet("结果");
List<String> heads = Arrays.asList("案件号", "分配对象", "逾期金额");
int rix = 0;
int hsize = heads.size();
Row row = sheet.createRow(rix++);
for(int i = 0; i < hsize; ++i) {
Cell cell = row.createCell(i);
cell.setCellValue((String)heads.get(i));
}
Iterator var28 = result.entrySet().iterator();
while(var28.hasNext()) {
Map.Entry<AssignDto, List<CaseDto>> entry = (Map.Entry)var28.next();
Iterator var12 = ((List)entry.getValue()).iterator();
while(var12.hasNext()) {
CaseDto dto = (CaseDto)var12.next();
row = sheet.createRow(rix++);
dto.setUserId(((AssignDto)entry.getKey()).getUserId());
for(int ix = 0; ix < hsize; ++ix) {
Cell cellx = row.createCell(ix);
switch ((String)heads.get(ix)) {
case "案件号":
cellx.setCellValue((double)dto.getCaseId());
break;
case "分配对象":
cellx.setCellValue(dto.getUserId());
break;
case "逾期金额":
cellx.setCellValue(dto.getAmtBal().doubleValue());
}
}
}
}
String uuid = UUID.randomUUID().toString().replace("-", "");
String newPath;
for(newPath = path.replace(".xls", "结果-" + uuid + ".xls"); (new File(newPath)).exists(); newPath = path.replace(".xls", "结果-" + uuid + ".xls")) {
uuid = UUID.randomUUID().toString().replace("-", "");
}
FileOutputStream out = null;
try {
out = new FileOutputStream(newPath);
book.write(out);
out.flush();
this.append("\n生成结果文件【" + newPath + "】");
} catch (Exception var24) {
this.append("\n生成结果文件【" + newPath + "】失败");
} finally {
if (out != null) {
try {
out.close();
} catch (IOException var22) {
this.append("关闭【FileOutputStream】失败");
}
}
}
if (CaseFrame.this.autoOpen.isSelected()) {
String[] cmd = new String[]{"explorer.exe", newPath};
try {
Runtime.getRuntime().exec(cmd);
} catch (Exception var23) {
this.append("\n打开文件失败【" + newPath + "】");
}
this.append("\n自动打开文件【" + newPath + "】");
}
}
private String cell2string(Cell cell, boolean nullToBlock) {
String value = null;
switch (cell.getCellType()) {
case 0:
if (DateUtil.isCellDateFormatted(cell)) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
value = sdf.format(cell.getDateCellValue());
} else {
DecimalFormat df = new DecimalFormat("#.##");
value = df.format(cell.getNumericCellValue());
}
break;
case 1:
value = cell.getStringCellValue();
break;
case 2:
value = cell.getCellFormula();
case 3:
case 5:
default:
break;
case 4:
value = String.valueOf(cell.getBooleanCellValue());
}
if (StringUtils.isNotBlank(value)) {
value = value.trim().replaceAll("\\s+", "").replaceAll(",", ",");
} else if (nullToBlock) {
value = "";
}
return value;
}
private List<String> row2list(Row row) {
List<String> heads = new ArrayList();
if (row != null) {
int cellNum = row.getLastCellNum();
for(int i = 0; i < cellNum; ++i) {
Cell cell = row.getCell(i);
if (cell != null) {
String feild = cell.getStringCellValue();
if (StringUtils.isNotBlank(feild)) {
heads.add(feild.trim());
}
}
}
}
return heads;
}
private boolean regex(String input, String regex) {
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(input);
return m.matches();
}
private void append(String text) {
System.out.println(text);
CaseFrame.this.area.append(text + "\n");
CaseFrame.this.area.paintImmediately(CaseFrame.this.area.getBounds());
}
private void printList(String head, Collection<?> list, boolean append) {
System.out.println("\n------------------------------ " + head + " ------------------------------");
if (append) {
CaseFrame.this.area.append("\n------------------------------ " + head + " ------------------------------\n");
}
list.forEach((a) -> {
System.out.println(a.toString());
if (append) {
CaseFrame.this.area.append(a.toString() + "\n");
}
});
if (append) {
CaseFrame.this.area.paintImmediately(CaseFrame.this.area.getBounds());
}
}
}
private class CleanListener implements ActionListener {
private CleanListener(CleanListener cleanListener) {
}
public void actionPerformed(ActionEvent e) {
CaseFrame.this.autoOpen.setSelected(false);
CaseFrame.this.area.setText("");
}
}
private class SelectListener implements ActionListener {
private SelectListener(SelectListener selectListener) {
}
public void actionPerformed(ActionEvent e) {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setCurrentDirectory(new File("."));
fileChooser.setFileSelectionMode(2);
fileChooser.setFileFilter(new FileNameExtensionFilter("Excel (*.xlsx, *.xls)", new String[]{"xlsx", "xls"}));
int result = fileChooser.showOpenDialog(new JFrame());
if (result == 0) {
File file = fileChooser.getSelectedFile();
CaseFrame.this.fileText.setText(file.getAbsolutePath());
}
}
}
}
相关依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
用到的实体bean
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.zpp.dto;
import java.math.BigDecimal;
public class AssignDto {
private String userId;
private BigDecimal percent;
private int assignNum;
private int realNum;
private BigDecimal assignAmt;
private BigDecimal realAmt;
private BigDecimal offset;
public AssignDto(String userId, BigDecimal percent) {
this.userId = userId;
this.percent = percent;
this.assignNum = 0;
this.realNum = 0;
this.assignAmt = BigDecimal.ZERO;
this.realAmt = BigDecimal.ZERO;
this.offset = BigDecimal.ZERO;
}
public String toString() {
return "用户=" + this.userId + ", 权重=" + this.percent + ", 应分数量=" + this.assignNum + ", 实际数量=" + this.realNum + ", 应分金额=" + this.assignAmt + ", 实际金额=" + this.realAmt + ", 偏差量=" + this.offset;
}
public String getUserId() {
return this.userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public BigDecimal getPercent() {
return this.percent;
}
public void setPercent(BigDecimal percent) {
this.percent = percent;
}
public int getAssignNum() {
return this.assignNum;
}
public void setAssignNum(int assignNum) {
this.assignNum = assignNum;
this.realNum = 0;
}
public int getRealNum() {
return this.realNum;
}
public void setRealNum(int realNum) {
this.realNum = realNum;
}
public BigDecimal getAssignAmt() {
return this.assignAmt;
}
public void setAssignAmt(BigDecimal assignAmt) {
this.assignAmt = assignAmt;
this.offset = BigDecimal.ZERO;
}
public BigDecimal getRealAmt() {
return this.realAmt;
}
public void setRealAmt(BigDecimal realAmt) {
this.realAmt = realAmt;
this.offset = this.realAmt.subtract(this.assignAmt);
}
public BigDecimal getOffset() {
return this.offset;
}
public void setOffset(BigDecimal offset) {
this.offset = offset;
}
}
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.zpp.dto;
import java.math.BigDecimal;
public class CaseDto {
private Long caseId;
private BigDecimal amtBal;
private String userId;
public CaseDto() {
}
public String toString() {
return this.caseId + "," + this.amtBal + "," + this.userId;
}
public Long getCaseId() {
return this.caseId;
}
public void setCaseId(Long caseId) {
this.caseId = caseId;
}
public BigDecimal getAmtBal() {
return this.amtBal;
}
public void setAmtBal(BigDecimal amtBal) {
this.amtBal = amtBal;
}
public String getUserId() {
return this.userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
}