Get price value from component advanced attributes to my html table


require 'sketchup.rb'

model = Sketchup.active_model
entities = model.entities
components = entities.grep(Sketchup::ComponentInstance)

unique_items = Hash.new { |hash, key| hash[key] = { count: 0, layers: [] } }

# Collect unique components

components.each do |component|
  name = component.name
  name = '#isimsiz#' if name.empty? 
  unique_items[name][:count] += 1
  unique_items[name][:layers] << component.layer.name
    
end

if unique_items.length > 0
  # Create dialog box.
  dialog = UI::HtmlDialog.new({
    :dialog_title => "MALZEME LİSTESİ VE ADETLERİ",
    :preferences_key => "GroupComponentSummary",
    :scrollable => true,
    :resizable => true,
    :width => 600,
    :height => 300,
    :min_width => 100,
    :min_height => 100,
    :max_width => 2200,
    :max_height => 1200
  })

  # Create table and populate each column with its own value.
  table = "<table style='width: 1000px; font-family: arial;' table border='0' align= 'center' cellspacing= '1' table cellpadding= '10'>"
  table += "<tr><th colspan='10' bgcolor= 'grey' height='50'>BİNA RAPORU</th></tr>"
  table += "<tr><th height='50' align= 'left' style='font-size: 14px; width: 10%;'>KATMAN</th><th align= 'left' style='font-size: 14px; width: 20%; '>MALZEME İSMİ</th><th align= 'left' style='font-size: 14px; width: 2%;'>ADET</th><th align= 'left' style='font-size: 14px; width: 10%;'>DURUMU</th><th align= 'left' style='font-size: 14px; width: 5%;'>FİYAT</th><th align= 'left' style='font-size: 14px; width: 25%;'>AÇIKLAMA</th><th align= 'left' style='font-size: 14px;'>MARKA</th><th align= 'left' style='font-size: 14px;'>İNTERNET SİTESİ</th></tr>"
  
  unique_items.each do |name, data|
    count = data[:count]
    layers = data[:layers]&.uniq&.join(', ') || ''
       
  component = components.find { |c| c.name == name }
  if component
  # Get price from component attributes
  price = component.get_attribute('SU_DefinitionSet', 'price') || ''
  item_type = 'bileĹźen'
  else
  price = '0'
  item_type = 'isimsiz bileĹźen'
  end
    
    table += "<tr  height='25' bgcolor= 'D3 D3 D3'><td>#{layers}</td><td>#{name}</td><td>#{count}</td><td>#{item_type}</td><td>#{price}</td><td></td><td></td><td>#{}</td></tr>"
  end        

 table += "</table>"
 dialog.set_html(table)
 dialog.show
else
    UI.messagebox("Bileşen bulunamadı.")
end

I want to create a command, like “generate report,” that I can use with a single command. However, when I try to call the “price” value dependent on the component, the table box appears empty. The same applies to the “url” and “owner” values. Can someone help me with this?

Don’t use String.+=. Use String.<< (append) instead. iE …

table = String.new

# later in the code ...
table << %[
  <table style='width: 1000px; font-family: arial;' table border='0'
  align= 'center' cellspacing= '1' table cellpadding= '10'>
]

… etc. …

Try getting the attribute from the instance’s definition …

  # Get price from component attributes
  price = component.definition.get_attribute('SU_DefinitionSet', 'price') || ''
1 Like
model = Sketchup.active_model
entities = model.entities
components = entities.grep(Sketchup::ComponentInstance)

components.each do |component|
  name = component.name
  price = component.definition.get_attribute('SU_DefinitionSet', 'price').to_f || ''

  if name.empty?
    puts "No İnstance Name"
  elsif price.nil?
    puts "#{name} - no entry value"
  else
    puts "#{name} - VALUE: #{price}"
  end
end

Thank you for your response. First of all, I am a beginner in coding. These are the values that I reached as a result of my research. I simplified my code to find the source of the problem. However, no matter what I do, I cannot display the “price” value in the “ruby console”. I don’t want to give up.

Ekran Alıntısı1

This is mainly because the attribute key is "Price" not "price", so #get_attribute is returning nil and nil.to_f evaluates to 0.0 (which is a kind of silent failure built into the #to_f method to prevent an exception that would cause code to stop executing. It is up to you [the coder] to code defensively and test return values for validity that makes sense in each scenario.)

Also, be aware that String#to_f also returns 0.0 when it does not begin with valid numeric characters. So, an empty String also returns 0.0 …

"".to_f
#=> 0.0

Also, you do not need the || '' expression after calling #get_attribute.
Use the 3rd argument to set the default return value, as in …

  cdef = component.definition
  price = cdef.get_attribute('SU_DefinitionSet', 'Price', '0.0')

In this pattern you ensure that the return value stored as price will always be a String.

It is often not good practice to have statements or methods that return various types. Although it is common in Ruby for methods to return nil upon failure, (and the API does this many places,) the code then needs to check for nil return immediately after such a call.

But as shown above in the case of #get_attribute you can avoid the nil validity test because it is built-into the method if you use the 3rd argument.

Your code has an elsif price.nil? clause that will always eval to false (as you wrote it,) because price would be a Float or an empty String.


So this works for me …

model = Sketchup.active_model
entities = model.entities
components = entities.grep(Sketchup::ComponentInstance)

components.each do |component|
  name = component.name
  cdef = component.definition
  price = cdef.get_attribute('SU_DefinitionSet', 'Price', '0.0')

  name = "No İnstance Name" if name.empty?
  puts "#{name} - VALUE: #{price}"
end
1 Like

Thank you very much. I ran the code in the console and it retrieved the values exactly as I wanted. I customized the code to my needs, and now it works perfectly.

1 Like