Jump to content

search symbolname with a wildcard *


paulvector2

Recommended Posts

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.

Link to comment

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

Link to comment

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.

Link to comment

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

Link to comment

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 :) )

Link to comment

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);

Link to comment

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

Link to comment

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;

Link to comment

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);

Link to comment
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...

Link to comment

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

Link to comment

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;

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...