2016-12-10 28 views
2

ユーザーがCSV/ExcelドキュメントをアップロードしてRooを使って解析できるようにしようとしていますが、それを理解する問題のビット。Rooを使ってRuby(Rails)を使ってExcelを解析する

現在のスクリプト

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)特定のヘッダーのデータを解析し、 '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'列のすべての内容が返されます。行を繰り返し処理するようになりました。

擬作業スクリプト

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 

予想通りこれは、実際に実行している、と私は今、レイク仕事にファイルを送り始めることができます。まだいくつかの反復作業を行っていますが、これは非常に近いです。

+0

ヘッダーを制御できません。ユーザーにヘッダーの名前と数量などの名前を付けてもらうことはできませんか?彼らにとってはより簡単になり、あなたはその慣習を守ることが確実になります – peter

+0

@peter私の代わりに貧しい言い回しがあるかもしれません。私は彼らに "CardName"を特に指定するように要求することができましたが、 'xlsx.row(1)'を取り込み、選択肢を返し、具体的に 'which is which'を教えたり、もし 'name'のようなものであれば、おそらく 'CardName'でしょう。 – DNorthrup

+0

Excelでテキストファイルをインポートすると、私はいつも嫌いなことがあります。また、ヘッダーローの行数はカウントされず、2行目から5行目タイトルの付いた一般的なヘッダーです。私は正しいヘッドネームで読み上げる例を挙げることができますが、あなたに選択させることではなく、あなたの例におけるputsやgetsがRailsサイト上で動作しないことを認識していますか? – peter

答えて

3

私は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)(当社headerrow)正規表現/時間で、それのインデックス/ iはインデックスを返し、hの周りの#{}はhをその値に展開し、最初のケースでは 'CardName'、/ h/iの最後にあるiはケースを無視することを意味するので、定数CardNameには、headerrowの文字列CardNameのインデックスが割り当てられます。 厄介なbegin rescue構造の代わりに、必要な定数がすべてconst_getに存在するかどうかを確認し、エラーを捕まえるのではなく、それを実行することができます。

EDIT代わりの

p [row[CardName], row[Item]]あなただけの、これはRailsのか、他のウェブサイトのユーザーとの対話の一部であることを行っている場合は、あなたよりtickierになるだろうことを覚えておいて、チェックして、何でもできますputsとexampleを得る。例:

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 
+0

うわー、本当に面白いです。 .indexラインは間違いなく私を捨てましたが、私はそれが何をしているのか理解しています。 .each |項目と同様、index |私は前にやっていた - まあ、同様の結果。 私はこれを修正することができますので、「Y」ヘッダーがある場合は「X」しますか?たとえば、 'CardName'、 'C​​ount'は100%必要ですが、 'Condition' 'Collection'などのような行はオプションですが、必要な場合があります。 私に例を挙げてもらえれば、それを拡大することができます。 – DNorthrup

+0

私の答えにいくつか追加しましたが、それはあなたが意味するものかどうかはっきりしていません。それぞれのヘッダーが存在するかどうかをチェックすることについて私が言ったことも参照してください。 – peter

+0

ああ、そうです。追加の説明のためにありがとう!私はそれをコントローラに移す作業をしなければならないだろうが、Rubyのバージョンはうまく動作している。 – DNorthrup

関連する問題