使用Roo和Ruby(Rails)来parsingExcel

我试图让用户上传一个CSV / Excel文档,并使用Roo(我见过的最常见的一个)parsing它,但我有一些问题搞清楚了。

当前脚本

require 'roo' xlsx = Roo::Excelx.new("./TestAppXL.xlsx") xlsx.each_row_streaming do |row| puts row.inspect # Array of Excelx::Cell objects end 

这是我能够得到的唯一工作 – 它返回看起来是JSONB的东西。

我想要做的是几个过程:

A)用户上传一张“卡片”列表到我的网站(尽量允许尽可能多的选项,CSV,Excel等)

B)它立即返回标题列表并询问“哪个标题是名称,数量等等?”

C)我parsing数据的具体标题,做'X'。

B是我主要需要帮助的。 我正努力弄清Roo。 我将无法控制标题,所以我不能使用数字列号。

(添加Rails标签,因为这将最终在一个控制器中,也许是一个更简单的方法来做到这一点)。

更新的脚本

我其实已经取得了很多进展。 仍然试图接近我原来的要求。

 require 'roo' require 'roo-xls' xlsx = Roo::Spreadsheet.open('Demo.xls') headers = xlsx.first_row puts xlsx.row(headers) puts "Which number header is the Card Name?" CardName = gets puts xlsx.column(CardName.to_i) # => Returns basic info about the spreadsheet file 

需要更多的获取逻辑,但目前,如果我把'3'它将返回列'CardName'的所有内容。 现在正在遍历行。

Psuedo工作脚本

 require 'roo' require 'roo-xls' xlsx = Roo::Spreadsheet.open('Demo.xls') headers = xlsx.first_row puts xlsx.row(headers) puts "Which number header is the Card Name?" CardName = gets.to_i specHeader = xlsx.cell(headers,CardName) xlsx.column(CardName).drop(0).each_with_index do |item, index| if index == 0 else puts item end end 

这实际上是按预期执行的,我现在可以开始将文件送入Rake作业。 仍然在进行一些迭代,但这非常接近。

我给了你一个通用的方法来从Roo电子表格中提取数据,这些数据基于几个标题名称,这些标题名称将是你的上传者使用的约定。

 require 'roo' require 'roo-xls' xlsx = Roo::Spreadsheet.open('Demo.xls') first_row = xlsx.first_row headers = ['CardName', 'Item'] headers.each{|h|Kernel.const_set(h, xlsx.row(first_row).index{|e| e =~ /#{h}/i})} begin xlsx.drop(first_row).each do |row| p [row[CardName], row[Item]] end rescue # the required headers are not all present end 

我想唯一需要解释的是headers.each{|h|Kernel.const_set(h, xlsx.row(first_row).index{|e| e =~ /#{h}/i})}

对于每个标题名,用const_set指定它在xlsx.row(first_row)(我们的标题行)中的索引,其中正则expression式/ h / i返回一个索引,h周围的#{}是将h扩展为其值, 'CardName'在第一种情况下,我在/ h / i结尾的意思是被忽略的情况,所以常数CardName被分配给了Cardrow中stringCardName的索引。 而不是相当笨拙的开始救援结构,你可以检查所有需要的常量是否与const_get一起存在,并根据该结果而不是捕获错误。

编辑

而不是p [row[CardName], row[Item]]你可以检查和做任何事情,只要记住,如果这将成为Rails或其他网站的一部分,与用户的交互将变得更加棘手比你的投入和得到的例子。 比如像

 headers = ['CardName', 'Item', 'Condition', 'Collection'] ... xlsx.drop(first_row).each do |row| if row[CardName].nil? || row[Item].nil? # let the user know or skip else condition, collection = row[Condition], row[Collection] # and do something with it end end