Java导出Excel数据到TXT时totAmount值错位问题求助
解决Java Excel汇总金额写入txt时第一行金额错误的问题
问题根源
你的代码大概率是在切换账单时先输出了初始值为0的汇总行,之后才累加该账单的金额,导致第一行的totAmount用了初始值而非实际汇总结果。
调整方案:先汇总,再输出
方案1:先全量汇总再写入(更简洁)
先用Map存储每个Bill对应的累计Amount,遍历完所有Excel行后,再将Map中的内容写入txt:
import java.io.BufferedWriter; import java.io.FileWriter; import java.math.BigDecimal; import java.util.HashMap; import java.util.Map; 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.xssf.usermodel.XSSFWorkbook; public class ExcelSummary { public static void main(String[] args) throws Exception { // 1. 读取Excel并汇总金额 Map<String, BigDecimal> billAmountMap = new HashMap<>(); try (Workbook workbook = new XSSFWorkbook("你的Excel文件路径.xlsx")) { Sheet sheet = workbook.getSheetAt(0); for (Row row : sheet) { // 跳过表头行,假设表头在第0行 if (row.getRowNum() == 0) continue; String bill = row.getCell(0).getStringCellValue(); // 假设Bill在第1列 BigDecimal amount = BigDecimal.valueOf(row.getCell(1).getNumericCellValue()); // Amount在第2列 // 累加金额:如果Map中已有该Bill,就相加;否则存入初始值 billAmountMap.put(bill, billAmountMap.getOrDefault(bill, BigDecimal.ZERO).add(amount)); } } // 2. 写入HVEN.txt文件 try (BufferedWriter writer = new BufferedWriter(new FileWriter("HVEN.txt"))) { for (Map.Entry<String, BigDecimal> entry : billAmountMap.entrySet()) { // 按需求格式化金额,比如保留1位小数,用逗号作为分隔符 String formattedAmount = entry.getValue().setScale(1, BigDecimal.ROUND_HALF_UP).toString().replace(".", ","); writer.write(String.format("Bill: %s, totAmount: %s%n", entry.getKey(), formattedAmount)); } } } }
方案2:逐行遍历并实时处理(适合大文件,减少内存占用)
如果Excel文件很大,不想一次性加载所有数据,可以逐行处理,切换Bill时输出上一个Bill的汇总结果:
import java.io.BufferedWriter; import java.io.FileWriter; import java.math.BigDecimal; 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.xssf.usermodel.XSSFWorkbook; public class ExcelSummary { public static void main(String[] args) throws Exception { String currentBill = null; BigDecimal currentTotal = BigDecimal.ZERO; try (Workbook workbook = new XSSFWorkbook("你的Excel文件路径.xlsx"); BufferedWriter writer = new BufferedWriter(new FileWriter("HVEN.txt"))) { Sheet sheet = workbook.getSheetAt(0); for (Row row : sheet) { if (row.getRowNum() == 0) continue; // 跳过表头 String bill = row.getCell(0).getStringCellValue(); BigDecimal amount = BigDecimal.valueOf(row.getCell(1).getNumericCellValue()); if (currentBill == null) { // 初始化第一个Bill currentBill = bill; currentTotal = currentTotal.add(amount); } else if (!currentBill.equals(bill)) { // 切换Bill时,先输出上一个Bill的汇总 String formattedAmount = currentTotal.setScale(1, BigDecimal.ROUND_HALF_UP).toString().replace(".", ","); writer.write(String.format("Bill: %s, totAmount: %s%n", currentBill, formattedAmount)); // 重置当前Bill和累计金额 currentBill = bill; currentTotal = amount; } else { // 同一Bill,累加金额 currentTotal = currentTotal.add(amount); } } // 处理最后一个Bill的汇总 if (currentBill != null) { String formattedAmount = currentTotal.setScale(1, BigDecimal.ROUND_HALF_UP).toString().replace(".", ","); writer.write(String.format("Bill: %s, totAmount: %s%n", currentBill, formattedAmount)); } } } }
关键调整点
- 避免提前输出初始值:确保只有在收集完当前Bill的所有金额后,才写入该行的汇总结果
- 金额格式化:按照需求将
BigDecimal转换为带逗号分隔的格式(比如254.5转成254,5) - 边界处理:别忘了处理Excel的表头行,以及最后一个Bill的汇总输出
内容的提问来源于stack exchange,提问作者Serenity
相关产品推荐
相关产品推荐

