Я создал задачу с граблями для импорта пользователей из Google Sheet. Поэтому я использую драгоценный камень Ру. Пока все работает, но я не могу заставить его работать без импорта первой строки (заголовков).
Это мой код:
require 'roo'
namespace :import do
desc "Import users from Google Sheet"
task users: :environment do
@counter = 0
url = 'https://docs.google.com/spreadsheets/d/{mycode}/export?format=xlsx'
xlsx = Roo::Spreadsheet.open(url, extension: :xlsx, headers: true)
xlsx.each do |row|
n = User.where(name:row[0]).first
user = User.find_or_create_by(id: n)
user.update(
name:row[0],
country_id:row[6]
)
user.save!
puts user.name
@counter += 1
end
puts "Imported #{@counter} lines."
end
end
Когда вы открываете лист, ваш код говорит headers: true
. Вы пытались превратить его в ложь? Или вы говорите, что это не работает, если установлено значение false?
Кроме того, вы используете .each
несколько иначе, чем пример в документации. В документе показан хеш с ключами, полученными из заголовков. Вы используете нотацию массива [n]
. Это работает?
Обновлено:
Попробуйте использовать .each
способом, более похожим на то, что написано в документации:
xlsx.each(name: 'Name', country_id: 'Country ID') do |row|
n = User.where(name: row[:name]).first
...
end
Строки «Имя» и «Идентификатор страны» являются лишь примерами; они должны быть текстом любого заголовка столбца, имеющего информацию name и country_id.
Отредактировал свой ответ другим предложением. Неудивительно, что headers: false
не работает; он указан в документации как опция для .parse
, но вы пытаетесь использовать его в .open
.
Спасибо! Я повторно использовал .each
из старого проекта, в который я импортировал из CSV вместо электронной таблицы. Я переписал его, но, к сожалению, заголовки все еще импортированы.
Хорошо, ты мог бы просто пропустить первую строку, не так ли? xlsx[1..-1].each
Я был так сосредоточен на заголовках, что даже не думал о том, чтобы полностью пропустить первую строку. К сожалению, ваше предложение приводит к следующей ошибке NoMethodError: undefined method [] for #<Roo::Excelx:0x00007f9c2858bd50>
Есть способ пропустить заголовки, он использует метод: each_row_streaming(offset: 1)
.
Он вернет массив со строками, пропуская заголовок, поэтому вам нужно получить значение с помощью метода .value
. В документации укажите его для объектов Excelx::Cell
, но он работает и для объектов Roo::Spreadsheet
.
Пример документация:
xlsx.each_row_streaming(offset: 1) do |row| # Will exclude first (inevitably header) row
puts row.inspect # Array of Excelx::Cell objects
end
Я пробовал true, false, first_row, но пока ничего не работает.