R脚本实现Excel转CSV:保留列类型、校验扩展名等需求求助
Excel转多CSV脚本:解决类型保留、扩展名校验与依赖精简问题
仅依赖readxl的基础R版本(无purrr)
# 获取用户输入的文件名 input_file <- readline("请输入Excel文件名(可带/不带扩展名):") # 文件扩展名校验与补全函数 check_extension <- function(file) { # 提取并转为小写扩展名 ext <- tolower(tools::file_ext(file)) # 判断是否为合法Excel扩展名 if (ext %in% c("xls", "xlsx")) { return(file) } else { # 无合法扩展名时自动补全.xlsx return(paste0(file, ".xlsx")) } } file_path <- check_extension(input_file) # 检查文件是否存在 if (!file.exists(file_path)) { stop("错误:文件不存在,请检查路径或文件名!") } # 获取所有工作表名称 sheet_names <- readxl::excel_sheets(file_path) # 遍历每个工作表,转换为CSV for (sheet in sheet_names) { # 读取工作表,自动识别列类型 df <- readxl::read_excel(file_path, sheet = sheet, col_types = "guess") # 处理日期列:转为字符串避免被转为Excel数值序列号 date_cols <- sapply(df, function(x) inherits(x, c("Date", "POSIXct", "POSIXlt"))) df[date_cols] <- lapply(df[date_cols], as.character) # 处理数值列:强制关闭科学计数法,保留原始精度 num_cols <- sapply(df, is.numeric) df[num_cols] <- lapply(df[num_cols], function(x) format(x, scientific = FALSE, trim = TRUE)) # 生成输出文件名(原文件名-工作表名.csv) output_name <- paste0(tools::file_path_sans_ext(input_file), "-", sheet, ".csv") # 写入CSV:禁用行名,空值留空,保留引号 write.table(df, output_name, sep = ",", row.names = FALSE, na = "", quote = TRUE) } cat("转换完成!所有工作表已保存为独立CSV文件。\n")
针对你的三个问题的具体解答
1. 确保转换过程中列类型与值完全一致
- 日期处理:readxl读取的日期会转为
Date/POSIXct类型,直接用基础write.csv会把日期转成Excel内部的数值序列号,因此需要提前将日期列转为字符串格式,保留可读的日期文本。 - 数值精度:基础
write.csv对大数值默认用科学计数法,通过format(x, scientific = FALSE)强制保留原始数值格式,避免精度丢失。 - 空值匹配:写入时指定
na = "",让CSV中的空值与Excel显示一致,不会出现NA字符串。 - 类型识别:用
read_excel(col_types = "guess")自动识别列类型,再通过sapply判断列类型后针对性处理,适配不同结构的Excel文件。
2. 文件扩展名校验函数
上述代码中的check_extension函数基于基础R的tools::file_ext实现:
- 自动提取输入文件名的扩展名并转为小写,避免大小写差异导致的判断错误;
- 若输入已带
xls/xlsx扩展名,直接返回原路径; - 若输入无扩展名或扩展名非法,自动补全
.xlsx(可根据需求修改为让用户选择扩展名); - 额外增加
file.exists检查,避免用户输入不存在的文件。
3. 用基础包替代purrr
直接使用基础R的for循环遍历工作表名称,完全替代purrr的map和walk2功能,整个脚本仅依赖readxl(tools是R基础包的一部分,无需额外安装)。
可选:tidyverse优化版本(更简洁)
如果允许使用tidyverse(含readr、purrr),代码更简洁且类型处理更省心,readr::write_csv会自动处理日期和数值格式:
library(tidyverse) library(readxl) input_file <- readline("请输入Excel文件名(可带/不带扩展名):") # 扩展名处理 check_extension <- function(file) { ext <- tolower(tools::file_ext(file)) if (ext %in% c("xls", "xlsx")) file else paste0(file, ".xlsx") } file_path <- check_extension(input_file) if (!file.exists(file_path)) stop("错误:文件不存在!") sheet_names <- excel_sheets(file_path) # 遍历转换 walk(sheet_names, function(sheet) { df <- read_excel(file_path, sheet = sheet) output_name <- str_glue("{tools::file_path_sans_ext(input_file)}-{sheet}.csv") write_csv(df, output_name, na = "") }) cat("转换完成!\n")
内容的提问来源于stack exchange,提问作者CecilF
相关产品推荐
相关产品推荐

