Impress - macro for generating random letters

Creating a macro - Writing a Script - Using the API (OpenOffice Basic, Python, BeanShell, JavaScript)
Post Reply
KiaZ
Posts: 3
Joined: Wed Mar 02, 2011 5:34 pm

Impress - macro for generating random letters

Post by KiaZ »

Hello everyone here, I searched all over the docs and on google but didn't find a good answer for my problem.
I'm not a programmer even if I know some php and javascript but just for pleasure. I'm a optometry student and I'm trying to create a random letters eye-test chart in Openoffice Impress : basically what I need to do is to fill every page of my presetation with random letters when switching from one slide to another.
Can someone give me a hint for implementing such a random generator ?

Thanks in advance,

KiaZ
Openoffice 3.2.1 on Ubuntu 10.10
User avatar
Charlie Young
Volunteer
Posts: 1559
Joined: Fri May 14, 2010 1:07 am

Re: Impress - macro for generating random letters

Post by Charlie Young »

A macro function for generating a random upper case letter is pretty simple. This one uses the Basic Rnd function, which is very bad, but may suffice for this purpose.

Code: Select all

Function RandomLetter() As String
	RandomLetter = Chr(Asc("A") + Int(26*Rnd))
End Function
If you want to include, say numerals, in addition to upper case letters, that shouldn't be too difficult to arrange.

To create an eye chart, it seems it may be desirable to generate a string of n such random characters with spaces between, like so

Code: Select all

Function RandomLine(n As Integer) As String
	Dim i As Integer
	Dim s As String
	
	s = ""
	for i = 1 to n
		s = s & RandomLetter
		if i < n then
			s = s & " "
		endif
	next i
	RandomLine = s
End Function
I made an Impress presentation to implement this stuff (attached). It only works with one slide at the moment (Slide 0), but you can recreate it any time by running the EyeChart macro. It has a routine to erase the slide, then plot it afresh like so

Code: Select all

Sub PlotEyeChart(Slide as Integer)
    
    Dim Doc as Object
    Dim TextBox As Object
    Dim tCursor As Object
    Dim tHeight As Single
    Dim d As Object
    Dim p as new com.sun.star.awt.Point
    Dim s as new com.sun.star.awt.Size
    Dim h As Long
    Dim w As Long
	Dim i As Integer
	                  
    Doc = ThisComponent
    EraseSlide(Slide)
    d = Doc.Drawpages(Slide)
    
	TextBox = Doc.createInstance("com.sun.star.drawing.TextShape")
	TextBox.TextAutoGrowWidth = False
	TextBox.TextAutoGrowHeight = False
	
	d.add(TextBox)
        
    s.Width = d.Width
    s.Height = d.height
    TextBox.setSize(s)
    
	p = TextBox.Position
	p.X = 0
    P.Y = 0
    TextBox.setPosition(p)
    TextBox.ParaAdjust = com.sun.star.style.ParagraphAdjust.CENTER
    tHeight = 192
    tCursor = TextBox.createTextCursor()
    tCursor.gotoStart(False)
    for i = 1 to 8
    	tCursor.ParaAdjust = com.sun.star.style.ParagraphAdjust.CENTER
    	tCursor.CharHeight = tHeight
 	tCursor.String=RandomLine(i)
    	tCursor.goRight(1,False)
    	tCursor.String=Chr(13)
    	tCursor.goRight(1,False)
    	tHeight = .6667*tHeight
    next i
End Sub
This erases the slide, then fills it with a TextShape, then uses a TextCursor to fill in the chart. Note that I have it hardcoded for 8 lines, each with with n characters, and each line is ~2/3 the height of the one above. The number of lines, height, font, etc., could all be fooled with.

Here's a sample run. If you can read the last couple of lines here, your eyes are better than mine (not saying much) :geek:
Sample Eye Chart
Sample Eye Chart
I guess it's not too bad. I can read the preview :)
 Edit: My initial post of the .odp had a careless mistake in the code. If anyone finds it, sorry, I fixed that one. 
Attachments
EyeChart.odp
Eyechart Presentation
(15.74 KiB) Downloaded 335 times
Apache OpenOffice 4.1.1
Windows XP
KiaZ
Posts: 3
Joined: Wed Mar 02, 2011 5:34 pm

Re: Impress - macro for generating random letters

Post by KiaZ »

Firtst of all thanks for trying to help me :) .
It seems to basically work running the macro manually.
Now whati I have to fix is to have 3 slides with different letter sizes and correct page format, and making the macro running every time I change the slides with the arrow keys (it's important that this event is binded to the arrow keys because I will use a "presenter" remote control to run the presentation) ...
Also .. I need to avoid repetition of the same letter 2 times on the same row and to avoid certain letters to be used.
My idea for the last thing is to use a char array filled with the 16 allowed characters and to get a random number beetween 0 and 16 to get the letter.
However, I have the ideas but I have many difficulties coming from web scripting (php/javascript) to understand this BASIC :( , but I really need this thing for a resarch work so I have to manage a way to implement it ...
Openoffice 3.2.1 on Ubuntu 10.10
User avatar
Charlie Young
Volunteer
Posts: 1559
Joined: Fri May 14, 2010 1:07 am

Re: Impress - macro for generating random letters

Post by Charlie Young »

KiaZ wrote:Firtst of all thanks for trying to help me :) .
It seems to basically work running the macro manually.
Now whati I have to fix is to have 3 slides with different letter sizes and correct page format, and making the macro running every time I change the slides with the arrow keys (it's important that this event is binded to the arrow keys because I will use a "presenter" remote control to run the presentation) ...
Also .. I need to avoid repetition of the same letter 2 times on the same row and to avoid certain letters to be used.
My idea for the last thing is to use a char array filled with the 16 allowed characters and to get a random number beetween 0 and 16 to get the letter.
However, I have the ideas but I have many difficulties coming from web scripting (php/javascript) to understand this BASIC :( , but I really need this thing for a resarch work so I have to manage a way to implement it ...
You have the right idea about the modifications needed to RandomLetter, except if 16 characters are allowed, the random number needs to be from 1 to 16, not 0 to 16. Replace ABCDEFGHIJKLMNOP in the AllowedChars assignment below with your 16 characters, and it should be ready to go.

Code: Select all

Function RandomLetter() As String
	Dim AllowedChars As String
	
	AllowedChars = "ABCDEFGHIJKLMNOP" 
	RandomLetter = Mid(AllowedChars,Int(16*Rnd)+1,1)
End Function
To get all unique characters on a line, evidently the line can't be more than 16 characters long, so try this, which throws away duplicates:

Code: Select all

Function RandomLine(n As Integer) As String
	Dim i As Integer
	Dim r As String
	Dim s As String
	if n > 0 and n <= 16 then
		s = ""
		s = s & RandomLetter & " "
		for i = 1 to n - 1
			r = RandomLetter
			do while InStr(s,r) > 0
				r = RandomLetter
			loop
			s = s & r
			if i < n then
				s = s & " "
			endif
		next i
		RandomLine = s
	else
		MsgBox("Illegal argument to RandomLine")
		RandomLine = "XXXXXXXXXXXXXXXX"
	endif
		
End Function
RandomLine isn't actually guaranteed to ever stop, but with strings that short it shouldn't be a real concern (though Rnd does return a lot more duplicates than it should).

I'll look into the thing with the arrow keys. If you can give some clues about the page formats and such, We can probably help.
Apache OpenOffice 4.1.1
Windows XP
FJCC
Moderator
Posts: 9280
Joined: Sat Nov 08, 2008 8:08 pm
Location: Colorado, USA

Re: Impress - macro for generating random letters

Post by FJCC »

To get a macro to run on a slide change, you can add an EventListener to the Presentation. Here is the skeleton of some code. I call the addListener routine with a button on the first slide or a tool bar button. The presentation then starts and you can put code in the SlideTransitioinStarted or SlideTransitionEnded routines.

Code: Select all

Sub addListener
Doc = ThisComponent
Presentation = Doc.Presentation
Listener = createUnoListener("EV_","com.sun.star.presentation.XSlideShowListener")
Presentation.Start()
Controller = Presentation.Controller
Controller.addSlideShowListener(Listener)
end sub

Sub EV_paused(oEv)
End Sub

Sub EV_resumed(oEv)
End Sub

Sub EV_slideTransitionStarted(oEv)
'Print "HERE I AM!"
End Sub

Sub EV_slideTransitionEnded(oEv)
End Sub

Sub EV_slideAnimationEnded(oEv)
End Sub

Sub EV_slideEnded(oEv)
End Sub

Sub EV_hyperLinkClicked(oEv)
End Sub

Sub EV_disposing(oEv)
End Sub
OpenOffice 4.1 on Windows 10 and Linux Mint
If your question is answered, please go to your first post, select the Edit button, and add [Solved] to the beginning of the title.
KiaZ
Posts: 3
Joined: Wed Mar 02, 2011 5:34 pm

Re: Impress - macro for generating random letters

Post by KiaZ »

static_eyechart.pdf
static pdf demo eyechart
(10.22 KiB) Downloaded 302 times
Well, the non repeating random stuff works fine, I have sobstitute the function with my own random letter.
However before setting the key thing I have to build the right page format. I attach a PDF version of what I need to get out, please refer to the first 2 slides, the red/green one is another kind of test.
I have to use a custom font called Sloan : how can I change the font in the PlotEyeChart function ?

thanks
Openoffice 3.2.1 on Ubuntu 10.10
User avatar
Charlie Young
Volunteer
Posts: 1559
Joined: Fri May 14, 2010 1:07 am

Re: Impress - macro for generating random letters

Post by Charlie Young »

KiaZ wrote:
static_eyechart.pdf
Well, the non repeating random stuff works fine, I have sobstitute the function with my own random letter.
However before setting the key thing I have to build the right page format. I attach a PDF version of what I need to get out, please refer to the first 2 slides, the red/green one is another kind of test.
I have to use a custom font called Sloan : how can I change the font in the PlotEyeChart function ?

thanks
Will look at .pdf shortly.

Actually, the last version of RandomLine had a small problem in that it added a space on the end of a 1 character line. Below is better

Code: Select all

Function RandomLine(n As Integer) As String
	Dim i As Integer
	Dim r As String
	Dim s As String
	if n > 0 and n <= 16 then
		s = ""
		s = s & RandomLetter & " "
		i = 1
		do while i < n 
			r = RandomLetter
			do while InStr(s,r) > 0
				r = RandomLetter
			loop
			s = s & r & " "
			i = i + 1
		loop
		RandomLine = trim(s)
	else
		MsgBox("Illegal argument to RandomLine")
		RandomLine = "XXXXXXXXXXXXXXXX"
	endif
		
End Function

Apache OpenOffice 4.1.1
Windows XP
User avatar
Charlie Young
Volunteer
Posts: 1559
Joined: Fri May 14, 2010 1:07 am

Re: Impress - macro for generating random letters

Post by Charlie Young »

KiaZ wrote:
static_eyechart.pdf
I have to use a custom font called Sloan : how can I change the font in the PlotEyeChart function ?
thanks
See the API docs on Character Properties. All you need in PlotEyeChart is to add one line:

Code: Select all

    tCursor = TextBox.createTextCursor()
    tCursor.CharFontName = "Sloan"  ' add this line
    tCursor.gotoStart(False)
I don't have that one.
Apache OpenOffice 4.1.1
Windows XP
User avatar
Charlie Young
Volunteer
Posts: 1559
Joined: Fri May 14, 2010 1:07 am

Re: Impress - macro for generating random letters

Post by Charlie Young »

Well, I did find the Sloan font, apparently designed for this sort of thing.

After looking at the pdf, and trying to do something based on my original naive concept, I gave up and tried a few different approaches with varying success. The one I've settled on for now is radically different and much more complicated than before. Instead of filling each slide with a Textbox and then using a TextCursor, I am plotting a TextBox for each letter. For starters, I define a Type (structure):

Code: Select all

Type EyeChart
	ChartLines As Integer  	'Rows of characters on the chart
	CharsPerLine			'Array of number of characters on each line
	LineHeights				'Array of heights in points for each line
End Type
I am also including the red and green chart for now, since I wanted to have more than two to work with. The charts are defined in Main like so

Code: Select all

Global Charts(2) As EyeChart

Sub Main
	Dim i As Integer
	
	Charts(0).ChartLines = 3
	Charts(0).CharsPerLine = Array(4,4,4)
	Charts(0).LineHeights = Array(54,42,34)
	Charts(1).ChartLines = 3
	Charts(1).CharsPerLine = Array(4,4,4)
	Charts(1).LineHeights = Array(30,25,22)
	Charts(2).ChartLines = 1
	Charts(2).CharsPerLine = Array(4)
	Charts(2).LineHeights = Array(52)
	for i = 0 to 2
		PlotEyeChart(i,Charts(i))
	next i
	addlistener
End Sub
And PlotEyeChart (which is the part that is far more complicated than before), sets up each of the 3 slides.

Many thanks to FJCC for the listener stuff, that saved a lot of work. The code to regenerate the slides on transition is just

Code: Select all

Sub EV_slideTransitionStarted(oEv)
	Dim Slide As Integer
	
	Slide = oController.getCurrentSlideIndex
	PlotEyeChart(Slide, Charts(Slide))
End Sub
I am having a problem though. Running Main calls addlistener and runs the slideshow, and the letters are randomly changed as desired when going from slide to slide except when going from the next-to-last slide to the last one. To get the last one to change, I have to go back two slides and then back to the last one (I am using the arrow keys, by the way). This means that the last slide is stuck if I only have a show of two slides. I am still looking at this problem.

The attached .odp also contains macros EyeChartBackground, PlotBackground, and EraseBackground which were used to set up the red and green slide (I tried my best to match the colors in the pdf exactly by using a color picker tool); these macros are not part of the action otherwise. I am also using all 26 letters. KiaZ knows what to do with that though. I guessed the line heights by pasting the pdf into writer and reading off the sizes.

Here is a run of the first slide:
Slide1.png
Slide1.png (9.55 KiB) Viewed 8854 times
Attachments
EyeChartx.odp
Latest Attempt at Eyecharts
(14.57 KiB) Downloaded 330 times
Apache OpenOffice 4.1.1
Windows XP
Post Reply