Counting solar modules in SketchUp

components
skelion
selection

#1

Hi!!

I use Sketchup (along with the Skelion plugin) extensively for making solar plant layouts (rooftops/groundmounts/carports/you name it). I’m a beginner with Sketchup, but have gotten so much better in just a month of use :smiley:
Now to my problem…
Usually while doing rooftops plants on large roofs (as large as 350’ x 200’ just to give you an idea of size), I divide the roof into smaller sections and label the number of modules in each section.
I am currently making a rooftop plant with more than 7000 modules spread over 3 roofs of very odd sizes and shapes. My concern is that I cannot count the number of modules in a particular section of the roof. The entity info shows me the number of modules in the whole model.

Is there a way that I can get a count of a particular entity in just a selected area in the model?

Thanks!!


#2

How about a Ruby one-liner ?

Select what you need to filter - we’ll keep just the panel components…

Open the Ruby Console and paste this in…
You need to change the ‘defname’ to suit what your panel’s component-definition is actually called…

n="defname";m=Sketchup.active_model;s=m.selection;i=s.length;s.to_a.each{|e|(i-=1;s.remove(e)) unless e.is_a?(Sketchup::ComponentInstance) && e.definition.name==n};puts "#{n} count #{i}";

Press ‘enter’ and the selection is filtered to include just instances of that component definition, the ‘count’ is reported in the Ruby Console, BUT you will also see that now Entity Info reports how many panels are selected…


#3

Another option would be to make the module a component and distribute instances in arrays. Use the report tool to give you counts of the modules.


#4

@TIG- That worked great!!

@DaveR- Aaaand that worked too!! Skelion is super cool.

I just did a little jig at my desk.

Thank you guys!! :penguin:


#5

Hi there, Really happy with this solution, I am looking for 3 variations on this solution. I tried
n=“defname”;
m=Sketchup.active_model;
s=m.selection;
i=s.length;
s.to_a.each{|e|(i-=1;s.remove(e)) unless e.is_a?(Sketchup::ComponentInstance) && e.definition.name==n};
puts “#{n} count #{i}”;

And it counts perfectly, but I have 3 different components that I want to count in my selections. Is there a way to make this code report a count for each of the components. Or even better is it possible to automatically make a count for all the different components in my selection or even better and BEST:

Anyone know a code that searches for 2 different instances of nested components in my selection?

Tanx a million.
Kind regards Erwin.


#6

Hi there TIG, Really happy with this solution, I am looking for 3 variations on this solution. I tried

n=“defname”;

m=Sketchup.active_model;

s=m.selection;

i=s.length;

s.to_a.each{|e|(i-=1;s.remove(e)) unless e.is_a?(Sketchup::ComponentInstance) && e.definition.name==n};

puts “#{n} count #{i}”;

And it counts perfectly, but I have 3 different MAIN components (with in it 2 different nested components) that I want to count in my selections. Is there a way to make this code report a count for each of the MAIN components. Or even better is it possible to automatically make a count for all the different components (MIAN and if possible nested) in my selection or even better and BEST:

Do you know a code that searches for the 2 different instances of nested components in my selection, and report a count?

Tanx a million.

Kind regards Erwin.


#7

Try something like this…

n1=“defname1”
n2=“defname2”
c1 = 0
c2 = 0

Sketchup.active_model.selection.grep(Sketchup::ComponentInstance).each{|e|
c1.next! e.definition.name == n1
c2.next! e.definition.name == n2
}

puts “#{n1} count {#c1}”
puts “#{n2} count {#c2}”

To count two definition’s’ instances.
For more simply expand to n2 & c3 etc…


#8

Im a smart guy but not at all familiar with this coding.

I made this out of it:
n1=“Oost 2m”;
n2=“West 2m”;
c1 = 0;
c2 = 0;
Sketchup.active_model.selection.grep(Sketchup::ComponentInstance).each{|e|
c1.next! e.definition.name == n1
c2.next! e.definition.name == n2
};
puts “#{n1} count {#c1}”;
puts “#{n2} count {#c2}”;

and get :
Error: #<SyntaxError: : syntax error, unexpected tIDENTIFIER, expecting end-of-input
n1=“Oost 2m”;
^>
SketchUp:1:in `eval’

What is going wrong? And is this command searching for nested components?
Hope you can and want to help. Tanx a lot in advance.
Erwin.


#9

I can see three problems with your copy of the code:

  • you have used curly quotes instead of straight double quotes, everywhere
  • you have added semicolons at the end of each line. They aren’t needed in Ruby
  • you have switched the # and { symbols in the second half of the last two lines.

Copy and paste this (below) into the Ruby console and press Enter, or copy and paste into a plain text editor such as Notepad or Notepad++ and save it with a .rb file extension.

n1="Oost 2m"
n2="West 2m"
c1 = 0
c2 = 0
Sketchup.active_model.selection.grep(Sketchup::ComponentInstance).each{|e|
c1.next! e.definition.name == n1
c2.next! e.definition.name == n2
}
puts "#{n1} count #{c1}"
puts "#{n2} count #{c2}"

To run the file, if you do it that way, use

load "/full/path/to/yourfolder/yourfilename.rb"

It runs without obvious error, but since I have no components with the same names as yours, it only shows 0 component counts.

This is what I get (in full) in the Ruby console when I run the code in an empty SU drawing:

n1="Oost 2m"
n2="West 2m"
c1 = 0
c2 = 0
Sketchup.active_model.selection.grep(Sketchup::ComponentInstance).each{|e|
c1.next! e.definition.name == n1
c2.next! e.definition.name == n2
}
puts "#{n1} count #{c1}"
puts "#{n2} count #{c2}"


Oost 2m count 0
West 2m count 0

#10

Interesting, i used semicolons in my first code wich did work

n="Oost-West 2m";
m=Sketchup.active_model;
s=m.selection;
i=s.length;
s.to_a.each{|e|(i-=1;s.remove(e)) unless e.is_a?(Sketchup::ComponentInstance) && e.definition.name==n};
puts "#{n} count #{i}";

With me it gives this error

Error: #<NoMethodError: undefined method `next!’ for 0:Fixnum>

:5:in `block in ' :4:in `each' :4:in `' SketchUp:1:in `eval'

Don’t know what goes wrong. Hope you can help.

Does this search for nested components too? Or do you know a method that does?
Tanx a lot, kind regards, Erwin.

UPDATE: In an empty file or when i dont select anything it does work. It returns 0 though in my full model and when i select panels i get the error noted above. Hope you can help.


#11

Not at my computer so I can’t check run your code snippet, but I can answer a couple of questions.

Semi-colons are needed in Ruby only when you pack multiple statements onto the same line, which is generally considered poor style (it can make code harder to read and has no effect on performance). Otherwise they have no effect, are ignored.

Your code searches only the model’s entities collection. It will not find nested instances.

By the way, you could use the grep method on selection to find component instances faster than the logic test in your each loop.


#12

The hash is inside the { } and is interpreted as the beginning of a comment.
It should be #{c1} and #{c2}


#13

@egillissen
Why not use Generate Report?

you can make different kind of reports and save them to the model (or Template)


#14

Ok, generate report does not work, it hangs and the search function i got first is doing what it needs to do so I would like to make that work.

This one works ans searches just for 1 entitie at a time. I would like it to search for 3 or for 2 nested.

n=“Oost-West 2m”;
m=Sketchup.active_model;
s=m.selection;
i=s.length;
s.to_a.each{|e|(i-=1;s.remove(e)) unless e.is_a?(Sketchup::ComponentInstance) && e.definition.name==n};
puts “#{n} count #{i}”;

This code below reports a count of 0 for both when i select nothing.

n1="Oost 2m"
n2="West 2m"
c1 = 0
c2 = 0
Sketchup.active_model.selection.grep(Sketchup::ComponentInstance).each{|e|
c1.next! e.definition.name == n1
c2.next! e.definition.name == n2
}
puts "#{n1} count #{c1}"
puts “#{n2} count #{c2}”

If I select things in my model and use the code it returns:
Error: #<NoMethodError: undefined method `next!’ for 0:Fixnum>

:5:in `block in ' :4:in `each' :4:in `' SketchUp:1:in `eval'

I’m not good with code so i don’t get what using grep method means. I would like to ask you guys to help me with the code.

Tanx a lot.


#15

Hi @john_mcclenahan and @TIG , could you try to make it search for a component that you have in your file? In an empty file with no components to find, it works with me too. It’s when he finds something that creates below error. And is there a code I can use to make it search for nested items? Tanx very much in advance.


#16

Hi @MikeWayzovski

Could it be generate report does not work because the file is too large. It contains 9000 solar panels…
And I got it to work in a smaller model, but then it just reports back all the nested items as quantity 1 with each instance on a new line in stead of adding them.

Kind regards, Erwin.


#17

I’m not great at Ruby, but what the error message is telling you is that there isn’t a method next! for a fixed number - you are trying to apply the method next to the variable c1 which you have initialized as 0.

The next! method doesn’t do this even when it is applied to an object for which it is valid, and anyway, it isn’t a valid method to apply to an integer.

I think what you want to do is to add 1 to c1 if the entity selected is an instance of “Oost 2m”.

I think it should go something like:

c1 += c1 if e.definition.name == n1

And that’s just a Ruby shorthand way of saying

c1 = c1 + 1 if e.definition.name == n1

#18

@john_mcclenahan
I go crazy behind my PC haha. Don’t get it anymore.
This code works:

n=“Oost-West 2m”;
m=Sketchup.active_model;
s=m.selection;
i=s.length;
s.to_a.each{|e|(i-=1;s.remove(e)) unless e.is_a?(Sketchup::ComponentInstance) && e.definition.name==n};
puts “#{n} count #{i}”;

But is only counts one instance. If we could make this work for more instances it would be amazing.

This code:

n1=“Oost 2m”
n2=“West 2m”
c1 = 0
c2 = 0
Sketchup.active_model.selection.grep(Sketchup::ComponentInstance).each{|e|
c1 += c1 if e.definition.name == n1
c2 += c1 if e.definition.name == n2
}
puts “#{n1} count #{c1}”
puts “#{n2} count #{c2}”

Doesn’t work and if i select or don’t select panels it gives

Error: #<SyntaxError: : syntax error, unexpected tIDENTIFIER, expecting end-of-input>
SketchUp:1:in `eval’

HELP?


#19

Just looking at it, I think you may have curly quotes in your first two lines and in your puts statements. What text editor are you using? You shouldn’t be getting or using them.

[Later]
Yes, you do.

And you havn’t got a proper CR/LF in front of the line c1=0

My text editor shows it as:

n1="Oost 2m"
n2="West 2m"c1 = 0
c2 = 0

I fixed those, and at least it runs in the ruby console without error in an empty drawing.

But it still reports counts of zero, when I change n1 and n2 to the names of two top level components in a drawing, and even when I remember to select all before running the code.

It isn’t incrementing the counts, even when the e.definition.name looks to be the same string as the value of n1 or n2 - the ‘if’ statements aren’t finding a match.

And at this point, I can’t see why not either. Sorry, needs someone with more Ruby experience to chip in here.

[Later]
I fiddled about a bit more. Not sure if I got rid of more invisible characters, and maybe my earlier suggestion of using the shortcut c1 += c1 isn’t right. But I ended up with this in a drawing of different types of woodworking cramps (or clamps…):

Clamps assorted.skp.zip (2.2 MB)

n1="Forge Steel cramp"
n2="Wooden cramp"
c1 = 0
c2 = 0
Sketchup.active_model.selection.grep(Sketchup::ComponentInstance).each{|e|
c1 = c1 + 1 if e.definition.name == n1
c2 = c2 + 1 if e.definition.name == n2
}
puts "#{n1} count #{c1}"
puts "#{n2} count #{c2}"

which produces this output with all cramps selected:

Forge Steel cramp count 1
Wooden cramp count 2
true

Those are the correct counts. And if I add or delete a copy of one of those two types of cramp, the count changes correspondingly.


#20

In only saw this now. WOW WOW WOW. So happy! It works! YES YES YES!!!
Thank you so much.
I made it this:
n1="Oost 2m"
n2="West 2m"
n3="Oost-West 2m"
c1 = 0
c2 = 0
c3 = 0
Sketchup.active_model.selection.grep(Sketchup::ComponentInstance).each{|e|
c1 = c1 + 1 if e.definition.name == n1
c2 = c2 + 1 if e.definition.name == n2
c3 = c3 + 1 if e.definition.name == n3
}
puts ""
puts "Totaal aantal " “#{n1}” " panelen = " "#{c1}"
puts "Totaal aantal " “#{n2}” " panelen = " "#{c2}"
puts "Totaal aantal " “#{n3}” " panelen = " "#{c3}“
puts “Totaal aantal panelen =”” #{c1+c2+c3*2}"
With this as a result.


Hopefully this will help others too!

quote=“john_mcclenahan, post:19, topic:46514”]
n1="Forge Steel cramp"
n2="Wooden cramp"
c1 = 0
c2 = 0
Sketchup.active_model.selection.grep(Sketchup::ComponentInstance).each{|e|
c1 = c1 + 1 if e.definition.name == n1
c2 = c2 + 1 if e.definition.name == n2
}
puts "#{n1} count #{c1}"
puts “#{n2} count #{c2}”
[/quote]