I've been able to gather enough info around here to learn how to select objects using CQL by their width/height, or their outline weight/color, or fill color, etc. And this has been really helpful, but to gather this info I have literally been made to perform dozens of searches in order to finally find each one by chance. Is there not a more clear resource somewhere? I'm aware of the CQL page: https://community.coreldraw.com/share/b/insider/posts/using-corel-query-language-cql-to-search-for-objects-in-coreldraw-documents
This is incredibly vague for someone like me and it doesn't show me how to find a font using CQL. I'm embarrassed to ask this community for help with complex macros because I feel like its asking for free work from the programmers who happen to be here. I want to do it all on my own (as much as I can) but I don't know where to look for the perhaps already published info. The link I posted talks about how to find "red" ... (Query:="@colors.find('red')
Ok, well what if I want to find a very specific CMYK red like C:0 M:80 Y:80 B:0? How am I to learn how to target that specific CMYK value with the perfect words for VBA? I can't find this info ANYWHERE and it is causing me hours upon hours of trial and error, guessing at what the code MIGHT be, with much failure although sometimes success. I've began to contemplate returning to college for programming classes, but I have a big doubt that those classes will help with VBA specifically, nevermind CQL.
Ranting aside (though I would really appreciate an answer to advice for where to go for more in depth CQL terms), at the moment what I need to know how to find with CQL is a specific font.
I know it should be so simple... query:="@font blahblahblah, but I tried all sorts of variations of this and only got errors because I didn't use the /perfect text/. Very aggravating, and again I hate to bother you guys with this kind of stuff... I'd much rather have a resource to go to where this kind of stuff is already spelled out in full and I don't have to bother anyone for my petty HOWTOs. Thanks for any help, sorry for the rant.
With respect to your frustration with trying to learn about CQL, I have been there myself - and I go back there on occasion! My knowledge is very incomplete, but it's better than it used to be.
In addition to Alex Vakulenko's piece that you linked to, I've also picked up some stuff from reading excellent posts from Shelby Moore - some of them here on the CorelDRAW Community forum, and some of them at (Alex V's) Oberon Place forum.
A lot more stuff can be used in CQL by going through COM. For finding items that use a specific font, try this:
1 2 3 4 5 6 7
Sub find_Arial() Dim sr As ShapeRange Set sr = ActivePage.Shapes.FindShapes(, cdrTextShape, True, "@com.text.story.font = 'Arial'") sr.CreateSelection End Sub
You may already be familiar with "Evaluate", but if not, be aware that it can be useful for testing out CQL expressions. One example:
1
MsgBox ActiveShape.Evaluate("@com.text.story.font")
Select a text shape, run the macro, and see that it returns "Arial" in the messagebox.
That doesn't help you "guess the magic words" - but it provides a way to test the magic words.
For the specific CMYK color thing, here is one way you could try:
Sub find_yellow() Dim sr As ShapeRange Set sr = ActivePage.Shapes.FindShapes(, , True, "@fill.color = cmyk(0,0,100,0)") sr.CreateSelection End Sub
Nice. Thanks! This has helped me to complete a working macro which is my most "complex" and thus time saving, yet. Since my coding knowledge is still very very limited, the code etiquette is surely horrendous and probably full of redundancy but I am learning and the macro does get me the result I needed, even though it surely takes longer to complete than it should. Also it is a Frankenstein work of code due to having parts pasted from other people's codes. Oddly yet thankfully, the replace font code I once grabbed from this site works much better when replacing its main line from what it was due to the example you (Eskimo) gave me with the COM part: "@com.text.story.font = 'Arial'"). I'm not proud of this macro code-wise, but I want to paste it here just in case someone might wish to tell me how to cut down on redundancy in my coding practices. If anyone wishes to do so, it will probably help if I explain why it is doing what it is doing.
First of all, I had initially started the code by copying the active selection. This somehow ran into errors in some of my selections so I removed that and just do a manual copy now, then run the code without the copying of an active selection, since the pasting to active layer works either way. Even though the code will obviously show what is happening, again, I'm saying why because I'd like to learn to make cleaner & shorter code when possible. So then, the image shows the before and after. This macro is applied to all of the content above the horizontal red line, and the vertical red line is just a zoomed in sample for clarity. Here we go. Create a new document to the specified size. Name the active layer, create a new layer and name it as shown, return back to the first layer to paste everything, flip, ungroup and deselect everything. Find all text, flip it back (clear transformations), deselect. Find all text, paste to layer above. This next part was a work around I found to the failed "align to page center (at least for X7, which is what I use). I do not really understand it, but it does the trick so... ok. Next part finds hairline (.003 in) and changes it to 1 pt (.01389). Then we find and delete white fills, red fills, and 6 inch width shapes (those being the fabric thumbnails, as I couldn't find a way to identify and delete powerclip objects). I think this next find of cmyk 100, 100, 100, 100 was pointless, but what follows is the replace font code I found here and mentioned before. It does as it says, and I added to it italics, normal font case, 12 pt and add to selection (this was really hard for me to figure out, haha). After all that, just finished up with moving the newly made tiny text up closer to the shapes they belong to and deselected. I haven't figured it out yet, nor looked very hard, but somewhere along the way in this macro, there are two empty fields of paragraph text (which I never use) so I ended the macro with finding and deleting all paragraph text. Oh and the Save at the end is just to bring up the Save As dialogue, as we are in a new Untitled doc now and its a good time to go ahead and make the file official. What a mess right!?!?! Any and all comments for improvement are welcome. If I could shorten this code, I imagine it would decrease the load/run time. That isn't my priority though as it only takes about 8 seconds to complete. What I would really like is to learn how to achieve processes like this with less code, if possible. Hope this wasn't too pathetic to witness, hahahh.
The code:Sub NewCuttingGuide()Application.CreateDocumentActivePage.SizeHeight = 24ActivePage.SizeWidth = 18ActiveLayer.Name = "Applique"Dim lrl As LayerSet lrl = ActivePage.CreateLayer("Labels")lrl.Name = "Labels"ActivePage.Layers.Bottom.ActivateActiveLayer.PasteActiveSelectionRange.Flip cdrFlipHorizontalActiveSelectionRange.UngroupAllActiveDocument.RemoveFromSelectionActivePage.Shapes.FindShapes(query:="@type = 'text:artistic' or @type = 'text:paragraph'").CreateSelectionActiveSelectionRange.ClearTransformationsActiveSelectionRange.RemoveFromSelectionActivePage.Shapes.FindShapes(query:="@type = 'text:artistic' or @type = 'text:paragraph'").CutActiveLayer.Above.ActivateActiveLayer.PasteActivePage.Shapes.All.AddToSelectionDim sr As ShapeRangeDim pw#, ph#ActiveDocument.ActivePage.GetSize pw, phActiveDocument.ReferencePoint = cdrTopMiddleSet sr = ActiveSelectionRangeIf sr.Count = 0 Then Exit Subsr.SetPosition pw / 2, ph / -1ActiveSelection.Move 0, 85#ActiveLayer.Shapes.All.RemoveFromSelectionApplication.RefreshActivePage.Shapes.FindShapes(query:="@outline.width = {.003 in}").CreateSelectionActiveSelection.Outline.Width = 0.01389ActiveSelection.Fill.ApplyNoFillActiveLayer.Shapes.All.RemoveFromSelectionActivePage.Shapes.FindShapes(query:="@colors.find('white')").CreateSelectionActiveSelectionRange.DeleteActivePage.Shapes.FindShapes(query:="@colors.find('red')").CreateSelectionActiveSelectionRange.DeleteActivePage.Shapes.FindShapes(query:="@width = {6 in}").Delete Set sr = ActivePage.Shapes.FindShapes(, , True, "@fill.color = cmyk(100,100,100,100)") sr.CreateSelectionDim tr As ShapeRangeDim t As ShapeSet tr = ActiveSelectionRange.Shapes.FindShapes(, cdrTextShape)For Each t In tr t.BreakApart t.Previous.AddToSelection ActiveSelection.Combine Next t Dim p As Page, s As Shape Dim i&, f$, fNew$ f = "Arial" 'your font to find fNew = "Adobe Caslon Pro" 'new font i = ActivePage.Index For Each p In ActiveDocument.Pages p.Activate Set sr = ActivePage.Shapes.FindShapes(, cdrTextShape, True, "@com.text.story.font = 'Arial'") For Each s In sr s.Text.Story.Font = fNew s.Text.Story.Italic = True s.Text.Story.Case = cdrNormalFontCase s.Text.Story.Size = 12 s.AddToSelection Next s Next p ActiveDocument.Pages(i).Activate ActiveSelection.Move 6, 3 ActiveDocument.RemoveFromSelection ActivePage.Shapes.FindShapes(query:="@type = 'text:paragraph'").DeleteActiveDocument.SaveEnd Sub
I have done similar stuff - automating reformatting of existing content - and it often involves a lot of fiddly work. Don't feel bad that you haven't solved it with some slick "five lines of code" solution; that may simply not be possible for this particular task!
You might pick up some speed by temporarily disabling some of the on-screen stuff that CorelDRAW normally does. As an example, try running these two macros that do the same job: start with selected objects, and create 200 duplicates in a rectangular array.
This version doesn't do anything to help with speed:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Sub dupe_array() Dim srOrig As ShapeRange Dim srDupe As ShapeRange Dim lngColumnCount As Long Dim lngRowCount As Long Const dblColumnDist As Double = 1.5 Const dblRowDist As Double = 1.5 Set srOrig = ActiveSelectionRange For lngColumnCount = 0 To 19 For lngRowCount = 0 To 9 Set srDupe = srOrig.Duplicate srDupe.CenterX = srOrig.CenterX + lngColumnCount * dblColumnDist srDupe.CenterY = srOrig.CenterY + lngRowCount * dblRowDist Next lngRowCount Next lngColumnCount srOrig.Delete End Sub
This version has the same code in it, but changes EventsEnabled to False and Optimization to True.
A CommandGroup is used in this version to "wrap up" all of the operations so that they appear as a single action in CorelDRAW's Undo list.
It also has some error handling, which is something that is important to do if EventsEnabled and Optimization are being changed (to change them back to normal settings even if the sub has generated an error).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
Sub dupe_array_2() Dim srOrig As ShapeRange Dim srDupe As ShapeRange Dim lngColumnCount As Long Dim lngRowCount As Long Const dblColumnDist As Double = 1.5 Const dblRowDist As Double = 1.5 On Error GoTo ErrHandler EventsEnabled = False Optimization = True ActiveDocument.BeginCommandGroup "duplicate stuff" Set srOrig = ActiveSelectionRange For lngColumnCount = 0 To 19 For lngRowCount = 0 To 9 Set srDupe = srOrig.Duplicate srDupe.CenterX = srOrig.CenterX + lngColumnCount * dblColumnDist srDupe.CenterY = srOrig.CenterY + lngRowCount * dblRowDist Next lngRowCount Next lngColumnCount srOrig.Delete ExitSub: ActiveDocument.EndCommandGroup Optimization = False EventsEnabled = True Refresh Exit Sub ErrHandler: MsgBox "Error occurred: " & Err.Description Resume ExitSub End Sub
Here's a video showing the "faster" version of the macro in operation:
VIDEO: duplicate things.
On the system that I am sitting at now, the first version takes ~7 seconds (~28 seconds if I have the Object Manager open, as it's being updated on-the-fly).
The second version takes <1 second (even with the Object Manager open; only updates once).
Wow, that is impressive! In all my research of this sort I've only come across "command groups" one or two times and although I do use a macro I found which contains a command group, I never understood why, nor the benefit. Now I know. And now I know when and why to use such a thing (in long coded macros, for sure, if not otherwise as well). As per usual and always, thank you very much, Eskimo. I have gained much respect from my boss as a valuable asset in the company I work for by beginning to learn this complex mesh between graphic designer and (jr) programmer of automation, previously non-existent in this company. I joke not, my boss (company owner) used to and initially taught me to manually select and mirror every single text object in every project like the example screen shot I posted above because he didn't know about Edit>Select All>Text then Object>Transformations>Clear Transformations. I initially didn't either, but with some digging and prodding, I have found many many great things about CorelDRAW. I was taught strictly Adobe in college, with no mention of scripting/macro/programming/etc. (and I don't appreciate that they overlooked this so vastly). Having some good Photoshop Action recording knowledge when I started with the company I'm with, I knew that there was no way I was going to sit there and manually flip back each text object on its center via Clear Transformation, even with a shortcut key assigned. Then I found that NO, I also won't even go up to the Edit drop down to select text, then go to the Object drop down to clear its mirror/transformation to get it back to normal even with all text selected. ....Just code it all in one click/button/key! This stuff is so fun, and I'm glad to be learning how to maximize production via automation, probably for the rest of my life.
I swear I meant to only write a sentence or two, but I seem to just ramble every time. Thanks again buddy!