readxl::read_xls 返回 "libxls 错误: 无法打开文件"

11

我有多个 .xls (~100MB) 文件,我想从中加载多个工作表(每个文件)到 R 中作为数据框。我尝试了各种函数,例如 xlsx::xlsx2XLConnect::readWorksheetFromFile,但它们总是运行很长时间(>15 分钟),永远无法完成,我不得不强制退出 RStudio 才能继续工作。

我还尝试了 gdata::read.xls,它确实可以完成,但每个工作表需要超过 3 分钟的时间,并且它无法一次提取多个工作表(这将非常有助于加快我的流程),就像 XLConnect::loadWorkbook 可以做到的那样。

这些函数执行所需的时间(我甚至不确定前两个是否会在更长时间内完成)对于我的流程来说太长了,我需要同时处理许多文件。有没有办法让它们更快地运行/完成?

在几个地方,我看到了使用函数 readxl::read_xls 的建议,它似乎被广泛推荐用于此任务,并且应该比每个工作表更快。然而,这个函数给了我一个错误:

> # Minimal reproducible example:
> setwd("/Users/USER/Desktop")
> library(readxl)
> data <- read_xls(path="test_file.xls")
Error: 
  filepath: /Users/USER/Desktop/test_file.xls
  libxls error: Unable to open file

我还进行了一些初步测试,以确保文件存在且格式正确:

> # Testing existence & format of the file
> file.exists("test_file.xls")
[1] TRUE
> format_from_ext("test_file.xls")
[1] "xls"
> format_from_signature("test_file.xls")
[1] "xls"

以上使用的test_file.xls文件可以在这里找到。

如果您有关于如何使第一个函数运行更快或使read_xls运行的任何建议,我们将不胜感激 - 谢谢!

更新(2019年12月14日):

似乎一些用户能够使用readxl::read_xls函数打开上面的文件,而另一些用户则不能,在Mac和Windows上都是如此,使用最新版本的RRstudioreadxl问题已经发布在readxl GitHub上,但尚未解决。

更新(2023年4月14日):

上述的 GitHub 问题集结了各种问题并提供了一种可能的解决方案,即先在 MS Excel 中打开和关闭文件,然后才能通过 `readxl::read_xls` 读取。可以理解的是,这不是最好的解决方案。上述问题没有更好的解决方案而被关闭,反而在 libxls 的 GitHub 上开了一个 相关问题,目前还没有解决方案。
8个回答

5

我下载了您的数据集,并以以下方式读取每个excel表格(例如“总览”和“地区”表格):

install.packages("readxl")
library(readxl)
library(data.table)

dt_overall <- as.data.table(read_excel("test_file.xls", sheet = "Overall"))
area_sheet <- as.data.table(read_excel("test_file.xls", sheet = "Area"))

最后,我得到了如下的数据(例如,“Area”工作表的部分数据集): enter image description here 同样地,你可以使用read_xls函数代替read_excel
我检查了一下,它也能正确地工作,而且速度更快,因为read_excelreadxl包中read_xlsread_xlsx函数的包装器。
此外,你还可以使用readxl包中的excel_sheets函数来读取Excel文件的所有工作表。
更新:
使用microbenchmark包对以下包/函数进行基准测试:gdata::read.xlsXLConnect::readWorksheetFromFilereadxl::read_excel
但是,XLConnect是基于Java的解决方案,因此需要大量RAM。 enter image description here

2
尝试卸载readxl包,重启RStudio并重新安装readxl。 同时尝试更新R和RStudio到最新版本(如果您的版本已过时)。 - red_quark
1
哦,那非常有趣。我希望它们能帮助您找到解决问题的方法。同时,我还有两个建议,可能会对您有所帮助:
  1. 尝试直接安装 Rcpp 包,这需要 Xcode(适用于OSX),这些都是 R 外部的依赖项。
- red_quark
2
尝试使用旧版本的readxl包打开您的Excel文件(例如,v.1.3.0、1.2.0、1.1.0等;所有存档版本都可以在此处找到:https://cran.r-project.org/src/contrib/Archive/readxl/)。您可以按照以下方式安装它(例如): if(!require(readxl)) { install.packages("https://cran.r-project.org/src/contrib/Archive/readxl/readxl_1.2.0.tar.gz", repos = NULL, type="source"); suppressPackageStartupMessages(require(readxl))} P.S. 在链接中,您可以指定任何存档包的版本。 - red_quark
1
当然不是。在使用readxl包加载Excel文件之前,我没有修改或打开过它。 我在Windows 10 Enterprise上运行代码(RAM 16 GB,64位)。 但是!当我尝试在RStudio Server(Ubuntu)中读取您的Excel文件时,我遇到了相同的错误:“libxls错误:无法打开文件”。 - red_quark
1
非常奇怪(我有 > sessionInfo() R version 3.6.1 (2019-07-05) Platform: x86_64-w64-mingw32/x64 (64-bit) Running under: Windows >= 8 x64 (build 9200) (Windows:Windows 10企业版,版本1803,OS构建17134.1006。处理器:Intel Core i7-8550U,64位操作系统)。 RStudio - 版本1.1.456(2018年7月19日) - red_quark
显示剩余8条评论

1
我发现下载文件后,无法立即使用read_xl打开文件,但如果在Excel中打开文件,保存并再次关闭文件,则read_xl可以顺利打开文件。
对于处理数百个文件的建议解决方法是构建一个小的C#命令行实用程序来打开、保存和关闭Excel文件。源代码如下,该实用程序可以使用Visual Studio Community Edition编译。
using System.IO;
using Excel = Microsoft.Office.Interop.Excel;

namespace resaver
{
  class Program
  {
    static void Main(string[] args)
    {
      string srcFile = Path.GetFullPath(args[0]);
      Excel.Application excelApplication = new Excel.Application();
      excelApplication.Application.DisplayAlerts = false;
      Excel.Workbook srcworkBook = excelApplication.Workbooks.Open(srcFile);
      srcworkBook.Save();
      srcworkBook.Close();
      excelApplication.Quit();
    }
  }
}

编译完成后,可以使用例如system2()从R中调用该实用程序。

1
在我的系统上,我必须使用 path.expand
R> file = "~/blah.xls"
R> read_xls(file)

Error: 
  filepath: ~/Dropbox/signal/aud/rba/balsheet/data/a03.xls
  libxls error: Unable to open file

R> read_xls(path.expand(file)) # fixed

0

重新保存文件,你就可以轻松解决问题。

我以前也遇到过这个问题,但我从你们的讨论中得到了答案。

我使用了read_excel()来打开那些文件。


你是指用Excel重新保存文件吗?是的,这个建议已经提出过了,但是当处理数百个文件时,这并不能解决问题(你可以想象在Microsoft Excel中打开和重新保存每个文件需要很长时间)。 - Brunox13
无论使用read_xls()还是read_excel()都没有区别 - 根据read_excel()文档,实际上read_xls()更好:"read_excel()调用excel_format()来确定路径是xls还是xlsx,基于文件扩展名和文件本身的顺序。如果您知道得更好并想要避免这种猜测,请直接使用read_xls()read_xlsx()。" - Brunox13

0
如果您从互联网下载了 .xls 数据,即使在 Ms.Excel 中打开它,也会首先弹出一个提示,询问您是否信任该来源,如下面的截图所示。我猜这就是 R(read_xls)无法打开它的原因,因为它被认为是不安全的。将其保存为 .xlsx 文件,然后使用 read_xlsx()read_excel()enter image description here

0

虽然这不是基于代码的解决方案,但我只是更改了文件类型。例如,我保存为csvxlsx,而不是xls。然后我像平常一样打开它。
这对我有用,因为当我打开我的xls文件时,弹出消息:"'file.xls'的文件格式和扩展名不匹配。该文件可能已损坏或不安全..."


0
我将提出一种不同的工作流程。如果您安装了LibreOffice,那么您可以通过程序将Excel文件转换为CSV文件。我使用Linux,所以我在bash中执行此操作,但我相信在macOS中也是可能的。
因此,请打开终端并导航到包含Excel文件的文件夹,并在终端中运行以下命令:
for i in *.xls
    do soffice --headless --convert-to csv "$i" 
done

现在在R中,您可以使用data.table :: fread 循环读取文件:

情况1:文件结构不同

如果文件的结构不同,则不希望将它们rbind在一起。 您可以在R中运行:

files <- dir("path/to/files", pattern = ".csv")
all_files <- list()
for (i in 1:length(files)){
  fileName <- gsub("(^.*/)(.*)(.csv$)", "\\2", files[i])
  all_files[[fileName]] <- fread(files[i])
}

如果你想要从列表中提取你所命名的元素到全局环境中,以便它们可以被转换为对象,你可以使用list2env函数:
list2env(all_files, envir = .GlobalEnv)

请注意两件事情:首先,在 gsub 调用中,斜杠的方向。其次,如果 list2env 中的命名元素与全局环境中的对象同名,则可能会覆盖全局环境中的对象。

场景 2:文件结构相同

在这种情况下,您很可能希望将它们全部合并到一起。您可以在 R 中运行:

files <- dir("path/to/files", pattern = ".csv")
joined <- list()
for (i in 1:length(files)){
  joined <- rbindlist(joined, fread(files[i]), fill = TRUE)
}

1
谢谢回复!我更喜欢完全使用R语言来解决问题,因为我正在为一个不太熟悉编程的朋友开发这个工作流程,所以我想交给她一个单一的可用脚本,而不是让她去终端操作。 - Brunox13

0

我曾经遇到过类似的错误,想分享一个短期解决方案。

library(readxl)
download.file("https://mjwebster.github.io/DataJ/spreadsheets/MLBpayrolls.xls", "MLBPayrolls.xls")
MLBpayrolls <- read_excel("MLBpayrolls.xls", sheet = "MLB Payrolls", na = "n/a")

在我的教室里的某些系统上出现以下情况(但在其他系统上没有):

错误:filepath: MLBPayrolls.xls libxls 错误:无法打开文件

临时解决方案是将 xls 文件的 URL 粘贴到 Firefox 中,并通过浏览器下载。完成后,我们可以运行 read_excel 行而不出错。

这是今天在 Windows 10 上发生的,使用 R 3.6.2 和 R Studio 1.2.5033。


谢谢,@Ryan!就像我在GitHub上提到的那样,OP中描述的问题是关于已经在本地下载的文件,所以这可能是一个不同的问题。 - Brunox13

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接