AppsScript通过JDBC调用MySQL存储过程时,如何准确获取DECIMAL类型值并以数字类型写入Google表格
AppsScript通过JDBC调用MySQL存储过程时,如何准确获取DECIMAL类型值并以数字类型写入Google表格
我完全理解你的困扰——处理货币数据时哪怕0.01的误差都不能接受,同时还要保证Google表格的数字格式正常生效。咱们来一步步解决这个问题:
首先拆解问题根源:
- 使用
getFloat()会把MySQL的DECIMAL精确小数转成浮点型,而浮点型本身存在精度丢失的特性,这就是你看到数值差0.01的原因。 - 用
getString()或者getBigDecimal().toFixed(2)虽然能拿到精确值,但结果是字符串类型,Google表格会把它当成文本内容,自然不会应用你预设的货币格式。
正确的解决方案:用getBigDecimal()转成JavaScript数字类型
MySQL的DECIMAL(15,2)类型,其数值范围对应的整数部分(乘以100后)远小于JavaScript Number类型的精确表示上限(2^53),所以完全可以安全地转成Number类型而不丢失精度。具体操作如下:
- 调用
results.getBigDecimal(1 + i)获取精确的BigDecimal对象 - 用
doubleValue()方法将其转成JavaScript的Number类型 - 保留原有的
wasNull()判断,处理空值情况
修改你代码里的循环部分:
for (let i = 1; i <= 12; i++) { let bd = results.getBigDecimal(1 + i); // 获取精确的BigDecimal对象 row.push(results.wasNull() ? null : bd.doubleValue()); // 转成Number类型 }
为什么这样可行?
BigDecimal会完整保留MySQL DECIMAL字段的精确值,不会出现浮点型的精度丢失问题doubleValue()转成的Number类型,对于DECIMAL(15,2)的数值来说是完全精确的(两位小数的数值可以被双精度浮点数精准表示)- 写入Google表格时,Number类型会被识别为数字,你之前设置的货币格式会自动生效
替换后的完整函数示例:
function displayYearlyTotals(ss) { let totalsTab = ss.getSheetByName("totals tab"); let year = totalsTab.getRange("A3").getValue(); let conn = Jdbc.getConnection(_dbUrl, _dbUsername, _dbPassword); try { let stmt = conn.prepareStatement('CALL spYearlyTotals(?)'); stmt.setInt(1, year); let results = stmt.executeQuery(); let data = []; while (results.next()) { let row = []; row.push(results.getString(1)); // 标签列 for (let i = 1; i <= 12; i++) { let bd = results.getBigDecimal(1 + i); row.push(results.wasNull() ? null : bd.doubleValue()); } data.push(row); } totalsTab.getRange(3, 1, data.length, 13).setValues(data); } finally { conn.close(); } }
这样修改后,你既不会有精度损失,Google表格的货币格式也能正常工作了。
内容来源于stack exchange
相关产品推荐
相关产品推荐

