OberonPlace.com Forums  

Go Back   OberonPlace.com Forums > Developer Forums > VBA > CorelDRAW/Corel DESIGNER VBA

Reply
 
Thread Tools Search this Thread Display Modes
  #1  
Old 16-03-2006, 09:24
knowbodynow knowbodynow is offline
Senior Member
 
Join Date: Mar 2006
Location: Hatsukaichi near Hiroshima
Posts: 434
Default Striping a word down to the first letter only

Hello, I'm trying to figure out a macro that will search for words on a page (artistic text only) and replace the word just the first letter. For example the words helicopter and hat, would both become just "h". I guess I need to use len but don't know how to chop characters off from the back. Any help would be appreciated.

Thanks,

Chris (Hunt)
Reply With Quote
  #2  
Old 16-03-2006, 13:49
Alex's Avatar
Alex Alex is offline
Administrator
 
Join Date: Nov 2002
Posts: 1,940
Blog Entries: 4
Default

Here you go.

Code:
Public Sub StripLetters()
    Dim sText As Shape
    Dim tr As TextRange
    
    For Each sText In ActivePage.FindShapes(Type:=cdrTextShape)
        Set tr = sText.Text.Story.Duplicate
        If tr.Length > 1 Then
            tr.Start = 1 ' Make the range point past the first letter
            tr.Delete
        End If
    Next sText
End Sub
Reply With Quote
  #3  
Old 16-03-2006, 20:10
knowbodynow knowbodynow is offline
Senior Member
 
Join Date: Mar 2006
Location: Hatsukaichi near Hiroshima
Posts: 434
Default

Thanks Alex, that works perfectly - and not a len in sight! One thing that confuses me and I've noticed it before is Text.Story.Duplicate. Is that the way characters are selected? Why duplicate? I find it confusing.

Thanks again,

Chris
Reply With Quote
  #4  
Old 16-03-2006, 23:44
Alex's Avatar
Alex Alex is offline
Administrator
 
Join Date: Nov 2002
Posts: 1,940
Blog Entries: 4
Default Using TextRange objects

Good question. I suspected that this might confuse other people too, so here is the scoop.

In CorelDRAW a text object is represented by the Shape.Text class. The text object contains a text stream which might span a few frames (if you have a chain of linked paragraph text objects - in that case, all those shapes will point to the same text stream).

A set of characters from the text stream is represented by a TextRange class. You can think of a TextRange as just a selection of text. A text range, is nothing more than two character positions in the text stream - the first and the last character of the text stream which identify the beginning/end of the range.

You can have many text ranges pointing to different parts of the same text stream. That is, you can have a text object with five words in it and have five text ranges pointing to each of the words.

In fact, almost anything you want to do with a text object you will do through the text range. Pretty much the same way you do it with keyboard and mouse. If you want to make some words bold, you select them first and then apply the bold attribute. That gray selection is the equivalent of the text range in obejct model.

You need to keep in mind that even though you might have several text ranges pointing to different parts of the text stream, they all are just two numbers - the position of the beginning/end of the range in the text stream. This means that if you had a range which included characters 1 through 4 and another one which included characters 5 to 10, and then delete range one, your second range will still point to characters 5 through 10 which now will be completely different characters. So you need to be careful when keeping several references to different text ranges at the same time.

There are many ways you can retrieve a text range from the text object. The biggest and most important one is Text.Story which is a text range that includes all the characters in the text stream. If you want to do something with all characters of the text, you want to use the Story property. You can easily get a smaller range by using Text.Frame.Range which includes only the text visible in the current text frame. You can get a collection of columns, paragraphs, lines, words, characters, etc.

Here is one example of how you can use text ranges:

Code:
Sub TestTextRange1()
    Dim s As Shape
    Dim tr1 As TextRange, tr2 As TextRange, tr3 As TextRange
    Dim tr4 As TextRange
    
    Set s = ActiveLayer.CreateArtisticText(2, 3, "Word1 Word2 Word3")
    Set tr1 = s.Text.Story.Words(1)
    Set tr2 = s.Text.Story.Words(2)
    Set tr3 = s.Text.Story.Words(3)
    
    ' Make the first word bold
    tr1.Bold = True
    ' ... and the second - double underlined
    tr2.Underline = cdrDoubleThinWordFontLine
    ' ... and the third one - red
    tr3.Fill.UniformColor.CMYKAssign 0, 100, 100, 0
    
    ' Make a copy of the second text range
    Set tr4 = tr2.Duplicate
    ' Now both tr2 and tr4 refer to the second word. Let's prove it
    tr4.ChangeCase cdrTextUpperCase
    tr2.Italic = True
End Sub
Here is how you would make the second paragraph of text all bold:

Code:
ActiveShape.Text.Story.Paragraphs(2).Bold = True
Here is how you change attributes of words 4,5, and 6 in the text:

Code:
ActiveShape.Text.Story.Words(4, 3).Italic = True
You can also go through paragraphs, lines, words, characters, etc of a given text range. That is, once you obtained a text range, you can drill down to some subranges. For example, to change a font of the second word of third paragraph to "Arial Black" you do the following:

Code:
ActiveShape.Text.Story.Paragraphs(3).Words(2).Font = "Arial Black"
And you can go backwards too. For example, if you have a text range containing a word, you can get a text range that contains the whole paragraph this word belongs to. The following example will get the text range of the currently selected text (provided that you are in the text edit mode). Then it will get the first full paragraph that contains the selection and selects it. This will have an effect of expaning your current selection to enclose the whole paragraph (e.g. select a word and run this macro, it will select the whole paragraph):

Code:
Sub SelectFirstPara()
    Dim tr As TextRange
    Set tr = ActiveShape.Text.Selection
    tr.Paragraphs(1).Select
End Sub
However if your current selection includes text from several paragraphs (e.g. you select the last word of paragraph 1 and first word of paragraph 2), then the above example will only select paragraph 1. You might want to select both paragraph 1 and 2. You can do this like so:

Code:
Sub SelectWholeParagraphs1()
    Dim tr As TextRange
    Dim nParaCount As Long
    
    Set tr = ActiveShape.Text.Selection
    nParaCount = tr.Paragraphs.Count
    tr.Paragraphs(1, nParaCount).Select
End Sub
Or you can use the All property of the corresponding text range collection to include all elements of that collection:

Code:
Sub SelectWholeParagraphs2()
    Dim tr As TextRange
    Set tr = ActiveShape.Text.Selection
    tr.Paragraphs.All.Select
End Sub
As you can see, text support in quite powerful and easy to use. I hope I give you enough information to get started digging more information... If you have any more questions, let me know.
Reply With Quote
  #5  
Old 12-04-2007, 22:41
knowbodynow knowbodynow is offline
Senior Member
 
Join Date: Mar 2006
Location: Hatsukaichi near Hiroshima
Posts: 434
Default

It's been a while but I have another question about replacing text and I wonder if anyone can help. I now know how to replace specific characters but what should I do to replace every character in a word with an underscore. I tried:

Code:
ActiveShape.text.Story.Characters.All = "_"
But this replaced the whole text with just one underscore. Currently I have a work around by doing lots of individual replaces:

Code:
s.text.replace "a", "_", False, ReplaceAll:=True
s.text.replace "b", "_", False, ReplaceAll:=True
s.text.replace "c", "_", False, ReplaceAll:=True
etc etc
What should I use to do the job properly?

Thanks,

Chris (Hunt)
Reply With Quote
  #6  
Old 13-04-2007, 09:04
Alex's Avatar
Alex Alex is offline
Administrator
 
Join Date: Nov 2002
Posts: 1,940
Blog Entries: 4
Default

Is it important to maintain formatting of individual characters? If not, then it should be very easy to replace the characters with "_".

Code:
Sub ReplaceAllChars()
    ActiveShape.Text.Story = String(Len(ActiveShape.Text.Story), "_")
End Sub
If you do need to replace each character with "_" and preserve each character's attributes, you will need to replace them individually:

Code:
Sub ReplaceAllChars()
    Dim trChar As TextRange
    For Each trChar In ActiveShape.Text.Story.Characters
        trChar.Text = "_"
    Next trChar
End Sub
However that would replace all the line breaks and other non-printable characters with "_" too, so you might need to check for this first:

Code:
Sub ReplaceAllChars()
    Dim trChar As TextRange
    For Each trChar In ActiveShape.Text.Story.Characters
        If trChar <> "" Then
            If AscW(trChar) >= 32 Then trChar.Text = "_"
        End If
    Next trChar
End Sub
Or you might need to replace letters only (A-Z) while keeping all other characters unchanged (commas, periods, colons, spaces, etc). In that case, just check for the current character being replaced to be in the appropriate range:

Code:
Sub ReplaceAllChars()
    Dim trChar As TextRange
    For Each trChar In ActiveShape.Text.Story.Characters
        If UCase(trChar) >= "A" And UCase(trChar) <= "Z" Then trChar.Text = "_"
    Next trChar
End Sub
Reply With Quote
  #7  
Old 13-04-2007, 20:31
knowbodynow knowbodynow is offline
Senior Member
 
Join Date: Mar 2006
Location: Hatsukaichi near Hiroshima
Posts: 434
Default

Thanks Alex, that's fantastic and as usual very thorough. Your first suggestion fits the bill perfectly for what I'm doing and the other examples are useful reference. Great stuff,

Best wishes,

Chris
Reply With Quote
  #8  
Old 16-04-2007, 12:50
LGD
Guest
 
Posts: n/a
Default

I hope everyone doesn't mind my jumping in on this, but I have a similar question, this is something I've been wanting to do for a while to save me some time, but never got around to figuring it out.

What I need to do is change the attributes of text at the end of a string of artistic text. The problem is, each time the macro is called, the length of the text string will be different, so it could be as simple as "xyz abc this is what I want to change" or it may be something like "qwertyuiop asdfghhkll zxcbvnm lkjhhg nbbvfd this is what I want to change" is there an easy way to do this?

Thanks

LD
Reply With Quote
  #9  
Old 16-04-2007, 22:57
Alex's Avatar
Alex Alex is offline
Administrator
 
Join Date: Nov 2002
Posts: 1,940
Blog Entries: 4
Default

Well, it all depends on how exactly you identify the part that needs to be changed.

If you expect the text string to end with particular words always, then you know the length of that string and you can just change the attributes of last N characters of the text.

Here is an example (it will make the last 29 letters of the text box bold):

Code:
Sub ChangeTextAttributes1()
    Dim tr As TextRange
    Set tr = ActiveShape.Text.Story
    tr.Start = tr.End - Len("this is what I want to change") - 1
    tr.Bold = True
End Sub
If you need to make sure that the text actually ends with the particular phrase and only then change the attributes, you can do it like this:

Code:
Sub ChangeTextAttributes2()
    Const TextToFind As String = "this is what I want to change"
    Dim tr As TextRange
    Set tr = ActiveShape.Text.Story
    If Right(tr.Text, Len(TextToFind)) = TextToFind Then
        tr.Start = tr.End - Len(TextToFind) - 1
        tr.Bold = True
    End If
End Sub
You might as well just need to find the phrase anywhere in the text and change its attributes (whether or not the phrase is at the end of the text or not):

Code:
Sub ChangeTextAttributes3()
    Const TextToFind As String = "this is what I want to change"
    Dim tr As TextRange, tr2 As TextRange
    Dim n As Integer
    
    Set tr = ActiveShape.Text.Story
    n = InStr(tr.Text, TextToFind)
    While n > 0
        Set tr2 = tr.Duplicate()
        tr2.SetRange n - 1, n + Len(TextToFind) - 1
        tr2.Bold = True
        n = InStr(n + Len(TextToFind), tr.Text, TextToFind)
    Wend
End Sub
Obviously, if you need something else, the solution might be slightly different too... It all depends on what you are trying to achieve.
Reply With Quote
  #10  
Old 19-04-2007, 15:14
LGD
Guest
 
Posts: n/a
Default

Thanks, Alex, the first example will help considerably. I do have another instance where I would want to change, actually set, the attributes of text that the macro itself is creating, but there's no way to know in advance what the text would be (could be a number, could be letters) or how long the whole text string is going to be.

Perhaps if I give a more exact example. What this part of the macro does is finds the file name of the current document and adds it to the document, and also appends the colors used in the file to the end (this is set manually). In the case of CMYK files, it's easy to know that the last words are going to be Cyan Magenta Yellow Black. But in the case of spot color files, there's no telling what the words will be or how many there will be.

Just being able to set the CMYK names will help a lot, though, thanks.

LD
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
First letter of text object changes to uppercase automatically Alex FAQ 1 16-05-2005 14:23
Letter and Number Counter ddonnahoe CorelDRAW/Corel DESIGNER VBA 5 05-11-2004 13:27


All times are GMT -5. The time now is 02:49.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
Copyright © 2011, Oberonplace.com