You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

批量读取含公式的Excel指定范围数据时大量返回NA的问题

问题

需要从289个Excel文件中提取「Main tab」工作表的I20:I21单元格范围数据并合并为DataFrame,这些单元格包含引用「input」工作表的公式(示例公式:=IF($C$21<1,$C$21*$I3,$I3)*I13+IF($C$21<1,$C$21*$I$3,$I$3))。使用readxl::read_excel编写的批量处理代码仅能正确读取约10个文件的数据,其余均返回NA值。使用的代码如下:

files <- list.files('.', pattern = '*.xlsx', recursive = TRUE)
estimation_list <- lapply(files, 
              function(x) {readxl::read_excel(x, sheet = "Main tab", range = "I20:I21", col_names = FALSE)}) %>% 
  bind_cols %>% 
  t %>% 
  data.frame

colnames(estimation_list) <- c('lower', 'upper bound')
estimation_list$project <- files
write.xlsx(estimation_list,"updated_estimates.xlsx")
解决方案

1. 强制触发Excel公式计算

readxl读取的是单元格的已计算结果,如果文件从未打开过、或Excel计算模式设为手动,公式不会自动计算,readxl就会返回NA。可以用openxlsx批量打开并保存文件,触发公式计算:

library(openxlsx)
lapply(files, function(x) {
  wb <- loadWorkbook(x)
  saveWorkbook(wb, x, overwrite = TRUE)
})

处理完所有文件后,再运行原读取代码。

2. 调整readxl读取参数

添加guess_max = Inf避免类型猜测错误,同时确保读取的是单元格值而非公式:

estimation_list <- lapply(files, 
              function(x) {
                readxl::read_excel(x, 
                                   sheet = "Main tab", 
                                   range = "I20:I21", 
                                   col_names = FALSE,
                                   guess_max = Inf)
              }) %>% 
  bind_cols %>% 
  t %>% 
  data.frame

3. 改用openxlsx读取数据

如果readxl兼容性仍有问题,换用openxlsx直接读取公式计算值,它对公式的支持更稳定:

library(openxlsx)
estimation_list <- lapply(files, function(x) {
  wb <- loadWorkbook(x)
  # 读取I20:I21(第9列,20-21行)的值
  vals <- readWorkbook(wb, sheet = "Main tab", rows = 20:21, cols = 9, colNames = FALSE)
  as.data.frame(t(vals)) # 保持和原代码一致的结构
}) %>% 
  bind_rows()

colnames(estimation_list) <- c('lower', 'upper bound')
estimation_list$project <- files
write.xlsx(estimation_list,"updated_estimates.xlsx")

4. 定位异常文件

先筛选出返回NA的文件,手动排查问题(比如工作表不存在、公式引用失效等):

# 逐个检查文件是否返回NA
check_results <- lapply(files, function(x) {
  df <- readxl::read_excel(x, sheet = "Main tab", range = "I20:I21", col_names = FALSE)
  any(is.na(df))
})
# 获取异常文件列表
na_files <- files[unlist(check_results)]
print(na_files)

内容的提问来源于stack exchange,提问作者Léa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 05:29:54