Count all groups and used component depending of the layer

Hi

I’m trying to count all groups and used component depending of the layer they have.

For exemple, I want to know how many “door” taged group and component i have and i want it to count for each definitions.

Eg. :
5 component White door
2 component Front door
1 group Back door

I tried different things. I’m able to get the nb of component used with definition.count_used_instances but i’m not able to count used instance if tagged

I’m able to count tagged instance, entity.is_a?(Sketchup::ComponentInstance) #&& entity.layer.name == "Door"

But it also count doors which are in not used component …

I’m king of stuck

Hi,

With this code, I’m able to list components of my active entities

	model = Sketchup.active_model
	entities = model.active_entities
	
	entities.each{ |entity|  
	if entity.is_a? Sketchup::ComponentInstance
		puts "yes it is (#{entity.definition.name}) (#{entity.name}) (#{entity.layer.name}) "
	end}
	

But not to list component in nested entites, and that’s kind of my goal :slight_smile:

Try this. It works for me in a small test

model = Sketchup.active_model
entities = model.active_entities

def analyze(entity)
  puts "yes it is (#{entity.definition.name}) (#{entity.name}) (#{entity.layer.name}) "
  entity.definition.entities.each{|subentity|
    if subentity.is_a? Sketchup::ComponentInstance
      analyze(subentity)
    end
  }
end

entities.each{ |entity|  
  if entity.is_a? Sketchup::ComponentInstance
    analyze(entity)
  end
}
1 Like

That’s so good !

Thank you.

I leave the thread open in case someone know a Sketchup function to do it.

Thank’s a lot

1 Like

You can create an empty hash with key (layer.name) and value (amount of components) every item check if key exist and update the value…
I’ll try this weekend…

1 Like

[menu]. File > Generate report can be grouped by Tag (Layer)
You will need to edit the standard report, though.

Hi Mike,

I used to work with “Reports,” but even after exporting, I still had to edit the CSV file to make it compatible with the software that requires the CSV data. By creating my own plugin, I can tailor the program to my specific needs and make it easier to use.

This script is just the first step of a larger project. :smiley:

I plan to add the ability to see at any time how many components I have in my project realtime.

Thank’s

This is better than previous. It counts all groups and components and report quantities and names

model = Sketchup.active_model
entities = model.active_entities

@counter = {}

def analyze(entity)
  puts "yes it is (#{entity.definition.name}) (#{entity.name}) (#{entity.layer.name}) "
  updateDict(entity)
  entity.definition.entities.each do |subentity|
    analyze(subentity) if subentity.respond_to?(:definition)
  end
end
def updateDict(entity)
  if @counter[entity.layer.name]
    previousCount = @counter[entity.layer.name][0]
    previousEntitiesNames =  @counter[entity.layer.name][1]
    @counter[entity.layer.name] = [ previousCount + 1 , previousEntitiesNames + '|' + entity.definition.name ]
  else
    @counter[entity.layer.name] = [ 1 , entity.definition.name ]
  end
end

entities.each do |entity|  
  analyze(entity) if entity.respond_to?(:definition)
end

@counter.each do |key, value|
  textToReport = ""
  allNames = value[1].split("|")
  uniqNames = allNames.uniq
  uniqNames.each do |n|
    textToReport = textToReport + n.to_s + " (" + allNames.count(n).to_s + ") "
  end
  puts "#{value[0]} group or components in #{key} named as: #{textToReport}"
end

(edited by Author acording @DanRathbun recomendations)

Do not place a space between method names and their argument list. This can confuse the Ruby interpreter.


Rather than “hard” class typing, you can use “duck typing”.
(If it walks, talks and acts like a duck, then it can be treated as a duck.)

:duck:

Ie …

… can become …

  entity.definition.entities.each { |subentity|
    analyze(subentity) if subentity.respond_to?(:definition)
  }

REF: Object#respond_to?

Edited!
Thanks again @DanRathbun ! Cleaner and faster… Your help is always welcome… (all ducks reported… :wink:)

You are still inserting a space before an argument list …

This can “come back to bite you” in the future.

Ie, Ruby can get confused between what is supposed to be an argument list and what is an expression enclosed in parenthesis.


Also, for readability sake, the { for a block should be spaced the same as if you used doend instead of {}.

Ie, not

entities.each{ |entity|  
  analyze(entity) if entity.respond_to?(:definition)
}

but

entities.each { |entity|  
  analyze(entity) if entity.respond_to?(:definition)
}

… just as you would if using …

entities.each do |entity|  
  analyze(entity) if entity.respond_to?(:definition)
end
1 Like

updated both

1 Like