【问题标题】:simple-spreadsheet not properly loading an xls file on ruby, but working properly on irb简单电子表格无法在 ruby​​ 上正确加载 xls 文件,但在 irb 上正常工作
【发布时间】:2014-04-01 01:52:00
【问题描述】:

我目前正在尝试使用 ruby​​ 2.1.1 打开和解析 this xls file。直接的方法是使用 simple-spreadsheet gem,它似乎不适用于这个特定的电子表格(以及其他一些电子表格):

require 'simple-spreadsheet'
s=SimpleSpreadsheet::Workbook.read('151.xls')
puts s.last_row #prints 5

但是,当我将这个确切的代码复制并粘贴到 irb 中时,我得到了正确的答案

2.1.1 :001 > require 'simple-spreadsheet'
 => true 
2.1.1 :002 > s=SimpleSpreadsheet::Workbook.read('151.xls')
 => #prints the entire contents of the spreadsheet
2.1.1 :003 > s.last_row
 => 154

使用 Roo 时会发生相同的行为(这是意料之中的,因为 simple-spreadsheet 使用 Roo 打开 .xls 文件):

require 'roo'
s=Roo::Excel.new('151.xls')
puts s.last_row #prints 5, should print 154

在 irb 上

2.1.1 :001 > require 'simple-spreadsheet'
 => true 
2.1.1 :002 > s=Roo::Excel.new('151.xls')
 => #prints the entire contents of the spreadsheet
2.1.1 :003 > s.last_row
 => 154

进一步挖掘,我尝试使用电子表格,因为它是 Roo 的 excel.rb 文件所必需的:

require 'spreadsheet'    
Spreadsheet.open('151.xls') do |book|
  rows=0
  book.worksheet(0).each do |row|
    rows+=1
  end
  puts rows#prints 5
end

然而,这就是奇怪的地方(呃);当我将最后一段代码复制并粘贴到 irb 中时,我得到了

2.1.1 :001 > require 'spreadsheet'    
 => true 
2.1.1 :002 > Spreadsheet.open('152.xls') do |book|
2.1.1 :003 >       rows=0
2.1.1 :004?>     book.worksheet(0).each do |row|
2.1.1 :005 >           rows+=1
2.1.1 :006?>       end
2.1.1 :007?>     puts rows
2.1.1 :008?>   end
5
 => nil 

我应该补充一点,宝石不只是打印 5;该行下方的每个单元格都返回 nil;他们实际上在此特定行之后停止解析文件。

所以这是我的问题:拳头,为什么 irb 的行为与 ruby​​ 不同?其次,为什么这些 gem 没有加载整个电子表格?第三,我该怎么做才能解决这个问题?

感谢您的帮助

【问题讨论】:

  • 您能确认您使用的是哪个版本的 ruby​​zip 吗?我正在尝试使用 0.9.9 并获得与您提到的一致的结果,但只是想确定一下。我注意到最新版本的 ruby​​zip 破坏了简单的电子表格。
  • 我有 ruby​​zip 1.1.2 和 0.9.9。读取 xlsx 文件时,我必须在需要简单电子表格之前添加“gem 'rubyzip', '
  • 看起来你可以在程序/irb 中执行Gem.loaded_specs['rubyzip'].version。确保首先执行适当的要求(例如 - require 'simple-spreadsheet'
  • simple-spreadsheet 和 roo 加载 ruby​​zip 0.9.9,无论是从控制台运行 ruby​​ 还是在 irb 中运行。但是,电子表格根本不加载 ruby​​zip。
  • 谢谢。我昨天看了这个,它看起来确实是一个非常奇怪的问题,尤其是 ruby​​ 程序和 irb 行为之间的差异。您能否制作一份电子表格的副本,但行数更少(比如 20 行而不是 154 行),看看它是否仍然具有相同的行为?如果它仍然只读取前 5 行,那么使用较小的文件将大大减少调试时间。

标签: ruby excel rubygems spreadsheet irb


【解决方案1】:

这是我见过的最奇怪的问题之一。回答您的问题:

首先,为什么 irb 的行为与 ruby​​ 不同?

IRB 是用 ruby​​ 编写的工具,与直接执行 ruby​​ 不同。主要区别之一是 IRB 具有可以在启动时设置的不同选项。您可以在source 中看到不同的标志,this page 对这些标志的含义有一些很好的描述。

您看到的不一致的罪魁祸首是--noinspect 选项,运行irb --noinspect 并执行您的代码应该会给您带来与运行ruby 程序相同的奇怪行为(您只能看到5 行)。这是因为 irb 默认在执行的每一行都调用 inspect,所以当你调用 s=SimpleSpreadsheet::Workbook.read('151.xls') 时,实际上就像在 ruby​​ 程序中调用它一样:

s = SimpleSpreadsheet::Workbook.read('151.xls')
s.inspect

为什么打电话给s.inspect 很重要?继续阅读...

其次,为什么这些 gem 没有加载整个电子表格?

这是最难回答的问题,我还没有 100% 准确地指出它,但希望 90% 的解释已经足够好了。简而言之,您提到的所有 gem 都依赖于 spreadsheet gem。在这个特定设置中该 gem 的一个怪癖/错误(我不认为它被设计为总是这样工作)似乎是它对 inspect 方法的依赖。如果您在工作表上调用inspect,它会比您不调用它时保留更多的值。也就是说,如果您不调用inspect,它只会读取文件的一部分(或读取其中的一部分而忽略其余部分,我不确定)但是如果您调用inspect,它会读取完全归档。

第三,我该怎么做才能解决这个问题?

正如我之前提到的,手动调用inspect 应该会读取整个文件:

s = SimpleSpreadsheet::Workbook.read('151.xls')
s.inspect

【讨论】:

  • 这太疯狂了,你是怎么想出来的?如果您确实查明了问题,请告诉我,但这可能与为什么与其他类似大小的其他宝石相比,宝石需要这么长时间才能阅读电子表格有关。我终于在 python 中编写了相同的代码,下载和解析大约 50 个电子表格需要几秒钟,而 ruby​​ 只需要 50 多秒来解析一个电子表格。我应该向电子表格的维护者开票吗?
  • 我最初尝试并排调试 2 个版本(ruby 程序与在 irb 中运行代码)。这并没有让我得到任何结果,所以最终我在研究 irb 的工作原理时很幸运。
  • 你说得对,代码似乎很慢,我怀疑这是spreadsheet gem (0.6.5.9) 的simple-spreadsheet depending on an old version 的问题。您可以提交问题以请求更新它,但由于 simple-spreadsheet 只是引用其他 gem,我可能会放弃它,转而使用更新版本的电子表格的 roo
  • 我还看到你有 submitted an issue with spreadsheet,这是我要建议的另一件事 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-23
  • 1970-01-01
  • 2018-07-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多