paulvector2 Posted October 10, 2008 Share Posted October 10, 2008 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? Quote Link to comment
Miguel Barrera Posted October 10, 2008 Share Posted October 10, 2008 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. Quote Link to comment
Pat Stanford Posted October 10, 2008 Share Posted October 10, 2008 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 Quote Link to comment
paulvector2 Posted October 11, 2008 Author Share Posted October 11, 2008 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. Quote Link to comment
Pat Stanford Posted October 12, 2008 Share Posted October 12, 2008 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 Quote Link to comment
maarten. Posted October 12, 2008 Share Posted October 12, 2008 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 ) Quote Link to comment
paulvector2 Posted October 12, 2008 Author Share Posted October 12, 2008 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 Quote Link to comment
maarten. Posted October 12, 2008 Share Posted October 12, 2008 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); Quote Link to comment
paulvector2 Posted October 12, 2008 Author Share Posted October 12, 2008 Thank you maarten for your quick answer. But my problem now is how to delete the doubles out of the array. Quote Link to comment
Pat Stanford Posted October 13, 2008 Share Posted October 13, 2008 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 Quote Link to comment
maarten. Posted October 13, 2008 Share Posted October 13, 2008 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; Quote Link to comment
paulvector2 Posted October 13, 2008 Author Share Posted October 13, 2008 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? Quote Link to comment
maarten. Posted October 13, 2008 Share Posted October 13, 2008 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); Quote Link to comment
maarten. Posted October 13, 2008 Share Posted October 13, 2008 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... Quote Link to comment
Pat Stanford Posted October 13, 2008 Share Posted October 13, 2008 Maarten, S=variable will not work, what will work is: AVariable:=concat('S=',OtherVariable); Count(AVariable); Pat Quote Link to comment
Pat Stanford Posted October 13, 2008 Share Posted October 13, 2008 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 Quote Link to comment
maarten. Posted October 13, 2008 Share Posted October 13, 2008 AVariable:=concat('S=',OtherVariable); Count(AVariable); That does work indeed. Thanks for the tip Pat . Haha, awesome, i learn something new every day . Quote Link to comment
Pat Stanford Posted October 13, 2008 Share Posted October 13, 2008 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 Quote Link to comment
paulvector2 Posted October 14, 2008 Author Share Posted October 14, 2008 Thanks Pat, Thanks Maarten for your help!!!!!!! Paul Quote Link to comment
paulvector2 Posted October 20, 2008 Author Share Posted October 20, 2008 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 Quote Link to comment
maarten. Posted October 20, 2008 Share Posted October 20, 2008 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; Quote Link to comment
paulvector2 Posted October 20, 2008 Author Share Posted October 20, 2008 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 Quote Link to comment
maarten. Posted October 20, 2008 Share Posted October 20, 2008 You can select multiple lines in a ListBoxN (a snap of a dialog with a list of the classes): 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 )... Quote Link to comment
paulvector2 Posted October 20, 2008 Author Share Posted October 20, 2008 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 Quote Link to comment
maarten. Posted October 20, 2008 Share Posted October 20, 2008 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. Quote Link to comment
Recommended Posts
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.