Jump to content
Developer Wiki and Function Reference Links Read more... ×
Sign in to follow this  
paulvector2

search symbolname with a wildcard *

Recommended Posts

I'm trying to make a script to list all symbols, which name contains the phrase 'window'. Is there something like a wildcard *?

Any suggestions?

Share this post


Link to post

No wildcards. You will need to iterate through all symbols and check if the substring 'window' is within the symbol name. You may use:

FUNCTION Pos(subStr, str :DYNARRAY[] of CHAR) :INTEGER;

If Pos is > 0 then the substring exists.

Furthermore, the function is case sensitive so you may have to convert both to upper case and then compare.

Share this post


Link to post

What is it you are really trying to do? There are several ways depending on your desired results.

Do you really need to do this in a script? If you just need a list, a worksheet may be a better solution.

Do you need just the symbols placed in the drawing? Or do you need to check all of the symbol definitions in the drawing? It make a difference in how you approach the problem.

If you can do it with criteria, you can kind of use wildcards. S='*window*' is the criteria generated by a Custom Selection script to symbol name contains window.

Pat

Share this post


Link to post

Dear Pat,

I'm trying to make a new drawing (layer), which contains all my symbols (in this case windows) placed in the drawing. My windowsymols are hybrid. So I make a new Layer, switch to 3D View 'front', search for all symbols, placed in the other layers of the Drawing, containing the substring 'window' and place them in the new Layer, labeled with name and quantity. All this with a script.

Share this post


Link to post

1. You can't make a new drawing with Vectorscript. It is limited to the document it is in.

2. You can create a new layer using the Layer('New Layer Name'); procedure. You also use this to change the active layer.

3. Since you are only interested in object that are already in the drawing, you should be able to do this with criteria. Try something like:

Procedure DoIt(H1:Handle);

Var X1,Y1,R1:Real;

Begin

Symbol(GetSDName(H1),X1,Y1,R1);

End;

Begin

ForEachObject(DoIt, S='*window*');

End;

You will need to work out how to adjust X1 and Y1 so they lay out properly.

It might be easiest to us the DoIt procedure to just go through and put all the symbol handles into an array and then sort and summerize the array. Then step through the array (from the bottom working up) and update your counts and then place the symbols in the drawing.

It can certainly be done. My guess is that it is about 200 lines of code to do this. At my usual rate of 20 lines an hour (after all the debugging is done), it would take about 10 hours to get this all done and tested.

If you need more help, let us know.

Pat

Share this post


Link to post

Paul, i have such a script that does somehow what you need. I only had to use it ones, so it isn't tested alot yet.

I just need to adjust some lines and translate my Variables into English, so you will understand it. If you want, i can post it, just say so.

(funny thing is, it's almost written as Pat says here above :) )

Share this post


Link to post

Dear Pat, Dear maarten,

thank you for your help. Yes maarten, i'm realy interested in your script. If you can post your code, it would help me a lot.

paul

Share this post


Link to post

Here you go :) :

{Maarten Vandickelen 2008}
PROCEDURE WindowsToLayer;
VAR
winH : DYNARRAY of HANDLE;
WinL : DYNARRAY of REAL;
WinN : DYNARRAY of STRING;
total : INTEGER;
count : INTEGER;
tmpS : STRING;
tmpCount : INTEGER;
cnt1,cnt2 : INTEGER;
tmpR : REAL;
tmpH : HANDLE;
pt1,pt2 : POINT;
ptN1,ptN2 : POINT;

PROCEDURE SetInfo(h : HANDLE);
BEGIN
	total:=total+1;
	ALLOCATE winH[1..total];
	ALLOCATE winL[1..total];
	ALLOCATE winN[1..total];
	winH[total]:=h;
	GetBBox(h,pt1.x,pt1.y,pt2.x,pt2.y);
	WinL[total]:=pt2.x-pt1.x;
	WinN[total]:=GetSymName(h);
END;

BEGIN
ForEachObject(SetInfo,S='*window*');
IF total<>0 THEN
BEGIN
{create new layer}
	tmpS:='New Layer';
	IF GetObject(tmpS)<>NIL THEN
	BEGIN
		REPEAT
			tmpCount:=tmpCount+1;
			IF GetObject(ConCat(tmpS,Num2Str(0,tmpCount)))=NIL THEN tmpS:=ConCat(tmpS,Num2Str(0,tmpCount));
		UNTIL(GetObject(tmpS)=NIL);
	END;
	Layer(tmpS);
{sort symbols by length}
	FOR cnt1:=1 TO total DO
	BEGIN
		FOR cnt2:=1 TO total-cnt1 DO
		BEGIN
			IF WinL[cnt2]>WinL[cnt2+1] THEN
			BEGIN
				tmpH:=WinH[cnt2];
				tmpR:=WinL[cnt2];
				tmpS:=WinN[cnt2];
				WinH[cnt2]:=WinH[cnt2+1];
				WinL[cnt2]:=WinL[cnt2+1];
				WinN[cnt2]:=WinN[cnt2+1];
				WinH[cnt2+1]:=tmpH;
				WinL[cnt2+1]:=tmpR;
				WinN[cnt2+1]:=tmpS;
			END;
		END;
	END;
{place symbol}
	FOR count:=1 TO total DO
	BEGIN
		IF count=1 THEN Symbol(winN[count],0,0,0) ELSE
		BEGIN
			GetBBox(LNewObj,pt1.x,pt1.y,pt2.x,pt2.y);
			Symbol(WinN[count],0,0,0);
			GetBBox(LNewObj,ptN1.x,ptN1.y,ptN2.x,ptN2.y);
		{move this symbol 50cm over the last symbol}
			HMove(LNewObj,pt2.x-ptN1.x+50cm,0);
		END;
	END;
END;
END;
RUN(WindowsToLayer);

Share this post


Link to post

I would add an extra field to the array, call it something like FirstOccurance.

Use the SortArray procedure to sort by the symbol name.

Step through the array. If the next line matches the first then mark it a FirstOccurance. Keep checking until you find a line that does not match. Repeat until you get to the end of the array.

SortArray again, this time based on the FirstOccurance. You should now have a single entry for each symbol type sorted to the top of the array.

Pat

Share this post


Link to post

Yes, that is a posibility. But you can also check before writing the info into the arrays if the name already is saved in the array.

	PROCEDURE SetInfo(h : HANDLE);
VAR
	cnt : INTEGER;
	bool : BOOLEAN;
BEGIN
	total:=total+1;
	ALLOCATE winH[1..total];
	ALLOCATE winL[1..total];
	ALLOCATE winN[1..total];
	FOR cnt:=1 TO total DO IF GetSymName(h)=WinN[cnt] THEN bool:=TRUE;
	IF NOT bool THEN
	BEGIN
		winH[total]:=h;
		GetBBox(h,pt1.x,pt1.y,pt2.x,pt2.y);
		WinL[total]:=pt2.x-pt1.x;
		WinN[total]:=GetSymName(h);
	END;
END;

Share this post


Link to post

Dear Pat, Dear Maarten,

i see here are masters at work and i'm just a greenhorn, like my membername says. So here is my last question. How can i now extract the quantity of each symbol out of the array and label my symbols?

Share this post


Link to post

Very odd, normally this would do it:

CreateText(Concat(Num2Str(0,Count(S=WinN[count])),' : ',WinN[count]));

But for some reason it doesn't work... Seems like Count(S=WinN[count]) doesn't work, no idea why :confused: .

Okay, an other (but longer) way to do this:

PROCEDURE WindowsToLayer;
VAR
winH : DYNARRAY of HANDLE;
WinL : DYNARRAY of REAL;
WinN : DYNARRAY of STRING;
WinQ : DYNARRAY of LONGINT;
total : INTEGER;
count : INTEGER;
tmpS : STRING;
tmpCount : INTEGER;
cnt1,cnt2 : INTEGER;
tmpR : REAL;
tmpH : HANDLE;
tmpL : LONGINT;
pt1,pt2 : POINT;
ptN1,ptN2 : POINT;

PROCEDURE SetInfo(h : HANDLE);
VAR
	cnt : INTEGER;
	bool : BOOLEAN;
BEGIN
	IF total>0 THEN FOR cnt:=1 TO total DO IF GetSymName(h)=WinN[cnt] THEN
	BEGIN
		bool:=TRUE;
		WinQ[cnt]:=WinQ[cnt]+1;
	END;
	IF NOT bool THEN
	BEGIN
		total:=total+1;
		ALLOCATE winH[1..total];
		ALLOCATE winL[1..total];
		ALLOCATE winN[1..total];
		ALLOCATE winQ[1..total];

		winH[total]:=h;
		GetBBox(h,pt1.x,pt1.y,pt2.x,pt2.y);
		WinL[total]:=pt2.x-pt1.x;
		WinN[total]:=GetSymName(h);
		WinQ[total]:=1;
	END;
END;

BEGIN
ForEachObject(SetInfo,S='*window*');
IF total<>0 THEN
BEGIN
{create new layer}
	tmpS:='New Layer';
	IF GetObject(tmpS)<>NIL THEN
	BEGIN
		REPEAT
			tmpCount:=tmpCount+1;
			IF GetObject(ConCat(tmpS,Num2Str(0,tmpCount)))=NIL THEN tmpS:=ConCat(tmpS,Num2Str(0,tmpCount));
		UNTIL(GetObject(tmpS)=NIL);
	END;
	Layer(tmpS);
{sort symbols by length}
	FOR cnt1:=1 TO total DO
	BEGIN
		FOR cnt2:=1 TO total-cnt1 DO
		BEGIN
			IF WinL[cnt2]>WinL[cnt2+1] THEN
			BEGIN
				tmpH:=WinH[cnt2];
				tmpR:=WinL[cnt2];
				tmpS:=WinN[cnt2];
				tmpL:=WinQ[cnt2];
				WinH[cnt2]:=WinH[cnt2+1];
				WinL[cnt2]:=WinL[cnt2+1];
				WinN[cnt2]:=WinN[cnt2+1];
				WinQ[cnt2]:=WinQ[cnt2+1];
				WinH[cnt2+1]:=tmpH;
				WinL[cnt2+1]:=tmpR;
				WinN[cnt2+1]:=tmpS;
				WinQ[cnt2+1]:=tmpL;
			END;
		END;
	END;
{place symbol}
	FOR count:=1 TO total DO
	BEGIN
		IF count=1 THEN BEGIN
			Symbol(winN[count],0,0,0);
			GetBBox(LNewObj,pt1.x,pt1.y,pt2.x,pt2.y);
			MoveTo(0,pt2.y);
			CreateText(Concat(Num2Str(0,WinQ[count]),' : ',WinN[count]));
			SetTextJust(LNewObj,2);
		END ELSE
		BEGIN
			GetBBox(LNewObj,pt1.x,pt1.y,pt2.x,pt2.y);
			Symbol(WinN[count],0,0,0);
			GetBBox(LNewObj,ptN1.x,ptN1.y,ptN2.x,ptN2.y);
		{move this symbol 50cm over the last symbol}
			HMove(LNewObj,pt2.x-ptN1.x+50cm,0);
		{write the quantity and name under the symbol}
			MoveTo(pt2.x-ptN1.x+50cm,ptN2.y);
			CreateText(Concat(Num2Str(0,WinQ[count]),' : ',WinN[count]));
			SetTextJust(LNewObj,2);
		END;
	END;
END;
{$debug}
END;
RUN(WindowsToLayer);

Share this post


Link to post
Very odd, normally this would do it:

CreateText(Concat(Num2Str(0,Count(S=WinN[count])),' : ',WinN[count]));

But for some reason it doesn't work... Seems like Count(S=WinN[count]) doesn't work, no idea why :confused: .

Well, i have a Variable that has the same name as a Function... That isn't that smart of course. So Paul, i thinks it's better to replace the Variable count by an other name (counter for example). (that's one of the reasons why i give my Variables a Dutch name :) )

But still, it seems that Count(S=a variable) doesn't work...

Share this post


Link to post

Maarten,

S=variable will not work, what will work is:

AVariable:=concat('S=',OtherVariable);

Count(AVariable);

Pat

Share this post


Link to post

Paul,

Several ways to handle this.

You can use Maarten's way and do a count after you have the list.

You can use my way and put another field in the array and increment the count when you clear out the duplicates.

You can use a combination and use Maarten's way to drop duplicate from every getting in the array and my way of adding an extra field and increment the count when you find a duplicate.

The best one is the one that gives the correct result (any of the above if coded correctly) and makes the most sense in your mind.

Pat

Share this post


Link to post
AVariable:=concat('S=',OtherVariable);

Count(AVariable);

That does work indeed. Thanks for the tip Pat ;) .

Haha, awesome, i learn something new every day :) .

Share this post


Link to post

I learned that from Julian (twice) about 5 years ago. Now that I have passed the tip on to someone else, I hope I remember it the next time I need it.

Thanks Julian!!

Pat

Share this post


Link to post

Hello Pat, Hello Maarten.

Your script works fine, so far. I added a dialog to enter a searchstring for the symbolnames in the drawing. Also this works fine. Now i wanted to add a browerList to limit the search only on layers, which i check. But this i can not make working. May you have an idea.

Paul

Share this post


Link to post

What is it exactly that doesn't work?

Here's a piece of a script of mine that will fill your ListBox. The id of the ListBox is 2000 in this example.

			PROCEDURE Dialooginstellingen;
		VAR
			tel : INTEGER;
			h : HANDLE;
		BEGIN
			h:=FLayer;
			FOR tel:=1 TO NumLayers DO
			BEGIN
				InsertChoice(2000,NumChoices(2000),GetLName(h));
				h:=NextLayer(h);
			END;
		END;

Share this post


Link to post

Dear maarten,

in this case ListBox is not the right choice i think, because you can only select layers in appropriate order, not for example the first layer in list the third and so on. I'm looking for a ListBrowser similar to the example listed under CreateLB in http://scs-inc.us/Other/VSFR/

Paul

Share this post


Link to post

You can select multiple lines in a ListBoxN (a snap of a dialog with a list of the classes):

afbeelding1te5.png

A listbrowser should work too, but is to complex in this case cause you can also adjust the visibility and such of the layers and you don't need that (i think :P )...

Share this post


Link to post

Dear maarten,

i use win and tried your script "LaagNaarDWG", but i can only select lines in order. What is your way doing it.

paul

Share this post


Link to post

While holding down ctrl and clicking on the requared lines, you should be able to select them. If i remember wel, it's the same on Windows.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

 

7150 Riverwood Drive, Columbia, Maryland 21046, USA   |   Contact Us:   410-290-5114

 

© 2018 Vectorworks, Inc. All Rights Reserved. Vectorworks, Inc. is part of the Nemetschek Group.

×