Retrieve first column value from TK::Tile::Treeview in Ruby - ruby

I try to retrieve the value of the first column from an item retrieved from a treeview using "item.get("#0")" but I got this error "RuntimeError: Display column #0 cannot be set". This method works for the other columns.
Can anyone help to figure out a solution?
Regards,
Marc
Here is a standalone example code:
require 'tk'
require 'tkextlib/tile'
$root = TkRoot.new
$frame = Tk::Tile::Frame.new($root)
$tree = Tk::Tile::Treeview.new($frame)
$tree['columns'] = ['action_text','action_description']
$tree.column_configure("#0", :width => 100)
$tree.heading_configure("#0", :text => 'la 1er colonne')
$tree.column_configure('action_text', :width => 100, :anchor => 'center')
$tree.heading_configure('action_text', :text => 'Text')
$tree.column_configure('action_description', :width => 100, :anchor => 'w')
$tree.heading_configure('action_description', :text => 'Description')
# Inserted at the root, program chooses id:
$tree.insert('', 'end', :id => 'widgets', :text => 'Widget Tour')
# Same thing, but inserted as first child:
$tree.insert('', 0, :id => 'gallery', :text => 'Applications')
# Treeview chooses the id:
item = $tree.insert('', 'end', :text => 'Tutorial')
# Inserted underneath an existing node:
$tree.insert( 'widgets', 'end', :text => 'Canvas')
$tree.insert( item, 'end', :text => 'Tree')
$tree.insert('', 2, :text => 'tata')
$tree.insert('', 'end', :text => 'envolee', :values => ['le centre', 'la description'])
$frame.grid(:column => 0, :row => 0, :sticky => 'nsew') {padding "3 3 12 12"}
$tree.grid(:column => 0, :row => 0, :sticky => 'nsew')
TkGrid.columnconfigure($root, 0, :weight => 1)
TkGrid.rowconfigure($root, 0, :weight => 1)
TkGrid.columnconfigure($frame, 0, :weight => 1)
TkGrid.rowconfigure($frame, 0, :weight => 1)
def create_action
item = $tree.selection_get[0]
puts item
puts "ID:"
puts item.id
puts "Index:"
puts item.index
puts "action_text:"
puts item.get('action_text')
puts "1:"
puts item.get('#1')
puts $tree.get(item.id, '#0')
puts "0:"
puts item.get("#0")
end
$tree.bind("Double-1") { create_action }
Tk.mainloop

I do not know if I understand exactly what you want to do,
item.text
might be a solution.

Related

Getting data from an array of hashes in ruby

I get an array of hashes from a google sheet, it looks like this
itemList = [ {:id => '1', :type => 'A', :category => 'Cat1' },
{:id => '2', :type => 'A', :category => 'Cat1' },
{:id => '3', :type => 'B', :category => 'Cat1' },
{:id => '4', :type => 'B', :category => 'Cat1' },
{:id => '1', :type => 'A', :category => 'Cat2' },
{:id => '2', :type => 'A', :category => 'Cat2' },
{:id => '3', :type => 'C', :category => 'Cat2' } ]
I would like to be able to print this on the terminal
Cat1
A
1, 2
B
3, 4
Cat2
A
1, 2
C
3
Is there an easy way to do it?
Thank you
Following will provide you required format,
items = itemList.group_by {|x| x[:category] }
val = items.inject({}) do |m,(k,v)|
tmp = v.group_by { |x| x[:type] }
m[k] = tmp.update(tmp) { |i,j| j.map { |x| x[:id] } }
m
end
# => {"Cat1"=>{"A"=>["1", "2"], "B"=>["3", "4"]}, "Cat2"=>{"A"=>["1", "2"], "C"=>["3"]}}
Display it like below,
val.each { |k,v| puts k; v.each { |i,j| puts i; puts j.join(', ') }; puts }
Cat1
A
1, 2
B
3, 4
Cat2
A
1, 2
C
3

Ruby Hash Of Array with Loop

I have this Hash:
{:id => [RN1223,BN3233], :name => ['Red Ring','Blue Bangles'], :category => ['Ring','Bangles']}
And I would like to get a new Hash with the following format:
{:id => 'RN1223', :name => 'Red Ring', :category => 'Ring'},
{:id => 'BN3233', :name => 'Blue Bangles', :category => 'Bangles'}
hsh = {:id => ['RN1223','BN3233'],
:name => ['Red Ring','Blue Bangles'],
:category => ['Ring','Bangles']}
hsh.values.transpose.map {|arr| Hash[[:id, :name, :category].zip arr]}
# => [{:id=>"RN1223", :name=>"Red Ring", :category=>"Ring"},
# {:id=>"BN3233", :name=>"Blue Bangles", :category=>"Bangles"}]

Compare two arrays of hashes and return new object

I have two arrays of hashes.
burgers = [
{:id => 1, :name => "cheese burger"},
{:id => 2, :name => "royale"},
{:id => 3, :name => "big mac"},
{:id => 4, :name => "angus beef"}
]
eaten = [
{:burger_id => 1},
{:burger_id => 2}
]
I would like to return an array or uneaten burgers, where burgers[:id] does not equal eaten[:burger_id]. In burgers_not_eaten_method, I have the expected return value.
def burgers_not_eaten
#Not sure how to compare burger[:id] with eaten[:burger_id]
burgers.reject { |burger| burger[:id] == #eaten burger_id }
# Expected: [{:id => 3, :name => "big mac"},{:id => 4, :name => "angus beef"}]
end
You're close, to make it easy I'd snag all the "eaten" ids into an array, and check for inclusion in that array, like so:
BURGERS = [
{:id => 1, :name => "cheese burger"},
{:id => 2, :name => "royale"},
{:id => 3, :name => "big mac"},
{:id => 4, :name => "angus beef"}
]
EATEN = [
{:burger_id => 1},
{:burger_id => 2}
]
def burgers_not_eaten
eaten_ids = EATEN.map { |e| e[:burger_id] }
BURGERS.reject { |burger| eaten_ids.include?(burger[:id]) }
end
burgers_not_eaten
# => [{:id=>3, :name=>"big mac"}, {:id=>4, :name=>"angus beef"}]

Find keep duplicates in Ruby hashes

I have an array of hashes where I need to find and store matches based on one matching value between the hashes.
a = [{:id => 1, :name => "Jim", :email => "jim#jim.jim"},
{:id => 2, :name => "Paul", :email => "paul#paul.paul"},
{:id => 3, :name => "Tom", :email => "tom#tom.tom"},
{:id => 1, :name => "Jim", :email => "jim#jim.jim"},
{:id => 5, :name => "Tom", :email => "tom#tom.tom"},
{:id => 6, :name => "Jim", :email => "jim#jim.jim"}]
So I would want to return
b = [{:id => 1, :name => "Jim", :email => "jim#jim.jim"},
{:id => 3, :name => "Tom", :email => "tom#tom.tom"},
{:id => 5, :name => "Tom", :email => "tom#tom.tom"},
{:id => 6, :name => "Jim", :email => "jim#jim.jim"}]
Notes: I can sort the data (csv) by :name after the fact so they don't have to be nicely grouped, just accurate. Also it's not necessary two of the same, it could be 3 or 10 or more.
Also, the data is about 22,000 rows.
I tested this and it will do exactly what you want:
b = a.group_by { |h| h[:name] }.values.select { |a| a.size > 1 }.flatten
However, you might want to look at some of the intermediate objects produced in that calculation and see if those are more useful to you.

I'm using the ruby gem "roo" to read xlsx file, how to return the content of one column as an array?

require 'gchart'
require 'rubygems'
require 'roo'
oo = Excelx.new("datav.xlsx")
oo.default_sheet = oo.sheets.first
2.upto(47) do |line|
data_a = [oo.cell(line,'B')]
data_b = [oo.cell(line,'E')]
chart_a = Gchart.new( :type => 'line',
:title => "A",
:theme => :keynote,
:width => 600,
:height => 500,
:data => data_a,
:line_colors => 'e0440e',
:axis_with_labels => ['x', 'y'],
:axis_range => [[0,50,20], [0,3000,500]],
:filename => "tmp/chart_a.png")
chart_b = Gchart.new( :type => 'line',
:title => "B",
:theme => :keynote,
:width => 600,
:height => 500,
:data => data_b,
:line_colors => 'e62ae5',
:axis_with_labels => ['x', 'y'],
:axis_range => [[0,50,20], [0,3000,500]],
:filename => "tmp/chart_b.png")
# Record file in filesystem
chart_a.file
chart_b.file
end
This will get every cell's content of column B and E to be the argument :data alone. How to return it as an array? If roo can't return array, then is there any else gem do this?
there is a column method that returns values of a given column as an array. Calling oo.column(2) should return you values for column B. oo.column('B') might work also. haven't tested it.
I needed the row back as a hash to be compatible with the logic I used for FasterCSV. This will give you a hash of the first row as the key and current line as the value.
def row_from_excel(s, line)
row = {}
s.first_column.upto(s.last_column) do |col|
cell_name = s.cell(1, col)
logger.debug "************* #{col} => #{cell_name} => #{s.cell(line, col)}"
row[cell_name] = s.cell(line, col)
end
row
end
s = Excelx.new(path_to_file) # or Excel.new(path_to_file)
2.upto(s.last_row) do |line|
row = row_from_excel(s, line)
end

Resources