Skip navigation.

Open Life

Opendocuments, Web Office, Office suites

Posts tagged with "BASIC"

Automating work with Basic II

, , ,

So this is the second part of my blog where I explain the logic used and how I got my script to run in OpenOffice.org.

The first thing I did was take a look and search on Andrew Pitonyak Macro book, to find a code that will come close to do what I have in mind.

The code is simple, this time I found a snippet that was able to select a cell. The original code was the following:
  Dim oCell
  Dim oSheet

  REM Get the first sheet.
  oSheet = ThisComponent.getSheets().getByIndex(0)
  REM Get cell A2
  oCell = oSheet.GetCellbyPosition( 0, 1 )
  REM Move the selection to cell A2
  ThisComponent.CurrentController.Select(oCell)


We can see in this snippet that the process is simple, simply get the sheet from the document and position the cursor on the sheet. Finally call on the CurrentController and use the native function of select.

Here we can see how this script go and how will it fit with our original design. My script needed to switch pages and go incrementally through the ammount of sheets in the spreadsheet.

What I did was obvious, I did a loop, my only concern was, what kind of loop. So far I found the for...next however there are the Do while, and Do Loop. I also needed a range since the loop can't go forever, and finally a way where it can get the data for the population of such things like the title.

I was going in a way to recreate the mail merge for spreads, the data however would be store in an array. The book also came handy at this point since I didn't exactly how to create arrays in OOoBasic.

The samples showed me the path and I was able to make a script that will look like this:
  firstDoc = ThisComponent
  for x = 0 to 14
  y= x
  oSheet= firstDoc.getSheets().getByIndex(y)
  
REM GetCellbyPosition will indicate the cell of the title 
REM SetString will insert the text into the cell
  
  oCell=oSheet.GetCellbyPosition( 1,2 )
  firstDoc.CurrentController.Select(oCell)
  oCell.SetString(title(x))

REM for additional modification include the following:
REM    Position of the cell -> GetCellPosition
REM    Content of the cell  -> SetString
  
  oCell2=oSheet.GetCellbyPosition( 0,1 )
  firstDoc.CurrentController.Select(oCell2)
  oCell2.SetString("Account 1")
  
  
  Next x


Of course that was not all their script and I also need to expand the script to not just label the first array but also static cell content that will be reapeated without major changes. In my script, this was the case with the title of the account, this required no datasource as the content should stay in place.

I also didn't show here the datasource but you can see how the datasource is handled, the array 'title' was able to have a counter instead of their values so the loop registration worked sequensially.

This script is extremely simple since you dont really need any UNO components and is basic loops will go through the created sheets, position on their cells and finally populate it with the infrmation of the array.

In the end the script looked like this:
REM  *****  BASIC  *****
REM
REM Script to insert sequencially the list of servers
REM to execute you need to select the starting page +1
REM and then select the ending page on the 'for Loop'
REM

'Load all the variables including the array
Sub LabelSheet
Dim oCell as Variant
Dim firstDoc as Variant
Dim oSheet as Variant
Dim title() as Variant
Dim titulo()
Dim x
REM title array takes the list from a CSV dump
title=Array("otherhost1",_
"otherhost2",_
"otherhost3",_
"otherhost4",_
"otherhost5",_
"otherhost6")


REM x works as a range, it start from the begining of the ARRAY
REM y is used to put the final starting page adding the value of
REM the "first page"

  firstDoc = ThisComponent
  for x = 0 to 6
  y= x
  oSheet= firstDoc.getSheets().getByIndex(y)
  
REM GetCellbyPosition will indicate the cell of the title 
REM SetString will insert the text into the cell
  
  oCell=oSheet.GetCellbyPosition( 1,2 )
  firstDoc.CurrentController.Select(oCell)
  oCell.SetString(title(x))

REM for additional modification include the following:
REM    Position of the cell -> GetCellPosition
REM    Content of the cell  -> SetString
  
  oCell2=oSheet.GetCellbyPosition( 0,1 )
  firstDoc.CurrentController.Select(oCell2)
  oCell2.SetString("Server")
  
  Next x
End Sub


So lets have an overview of the script:
  • Select a variable
  • Populate the array
  • get the document
  • for loop with the start of the number of array data
  • y variable was put in case you need to start in a document other than 0
  • oSheet selects the sheet in the document
  • oCell gets in the cell
  • Select the cell
  • Insert value with set string from the Array
  • Repeat the process but this time with static as opposed to the loopy title array
  • finish the sub

Automating work with Basic

, , , ...

Ok let's get this first stated: I am not a developer. I am a blood sucking leach feeding on the work of others. I don't produce code, I just modify it enough to fit my needs.

Once that said, you can argue that I am just in learning mode so eventually I will be part of the producting part of the FLOSS society and produce code from my own. Meanwhile I know enough to use code from other people to rearange my work and automate it.

I currently work in an enviroment full of hardcore techies, they love their bash scripts. However just like any other techie, they run away from documentation. I have been the only brave one to come up with some backbone and get on the challenge to document each of our 200 servers.

This however become easier task as I made an OpenOffice.org script to automate the task of scripting. However if you put attention earlier, I am not a programmer, however I only know enough to get the core code I need to get to my goal.

This is when I went to one of my community buddy's website Pitonyak.org and took a look at his cookbook which is full of snippet of code to do almost anything in OpenOffice.org through the use of OOoBasic.

This code include very interesting stuff such as:
  • Variable, Arrays and functions
  • UNO and Interfaces
  • Printing documents
  • Changing language of OOo
  • Load a document from a URL
  • Graphic manipulation, etc

This is just the begining of a 500pages long document with all kind of snippets. So how did this help me? Well I just start gluing this snippets and create the script I needed to automate my work.

The Document
The documentation consisted on a s series of spreadsheet documents full of data. Each sheet will be dedicated to each server, and each file will be dedicated for each account. The whole documentation consisted on at least 4 accounts.

Fortunately the servers were somewhat the same, they had the same profile and just duplicating the page will be enough. However, there was a problem.

The duplication of pages took too much, a series of clicks were needed and in the end the sheet still needed to be update for the righ server.

A mail merge will be so good in this case however the way the documentation was worked on, mail merge was not obvious.

Here is where OOoBasic came and Andrew's Pitonyak book was fundamental.

The script
The script language that OpenOffice.org uses by default is OpenOffice.org Basic. This language is similar to Microsoft VBScript, however it uses OpenOffice.org native API called UNO.

So first I needed to do is put a set of goals that the script needed to achieve and separate it into steps:
  • Select all the document
  • Being able to copy it
  • Generate a new document
  • Paste into the document
  • Generating a new sheet
  • Make the sheet name consistant

The next step beside duplicating the sheet was generating another script to what I called 'labeling the sheets'. This label process also had different steps that will follow another logic, similar in esence but the script actually change a lot.
  • Being able to select a specific cells
  • Insert a text into the cell
  • Load the data into a datasource just like an array
  • being able to extract that data from another spreadsheet which listed the server names.


Lets get to work
Ok boys and girls, the first step is to open the OOoBasic IDE. To open this, you need to go to Tools > Macros > Organize Macros > OpenOffice.org Basic. That will open the IDE and start to write the code.

First I went to Andrew's script on duplicating a file. This was not the code I needed exactly but it got close enough. This script will generate a new document. The topic number 6.18.1 Copy entire sheet to a new document.

'Author: Stephan Wunderlich [stephan.wunderlich@sun.com] 
Sub CopySpreadsheet
  firstDoc = ThisComponent
  selectSheetByName(firstDoc, "Sheet2")
  dispatchURL(firstDoc,".uno:SelectAll")
  dispatchURL(firstDoc,".uno:Copy")
  secondDoc = StarDesktop.loadComponentFromUrl("private:factory/scalc","_blank",0,dimArray())
  secondDoc.getSheets().insertNewByName("inserted",0)
  selectSheetByName(secondDoc, "inserted")
  dispatchURL(secondDoc,".uno:Paste")
End Sub

Sub selectSheetByName(document, sheetName)
  document.getCurrentController.select(document.getSheets().getByName(sheetName))
End Sub

Sub dispatchURL(document, aURL)
  Dim noProps()
  Dim URL As New com.sun.star.util.URL

  frame = document.getCurrentController().getFrame()
  URL.Complete = aURL
  transf = createUnoService("com.sun.star.util.URLTransformer")
 transf.parseStrict(URL)

  disp = frame.queryDispatch(URL, "", com.sun.star.frame.FrameSearchFlag.SELF _
         OR com.sun.star.frame.FrameSearchFlag.CHILDREN)
  disp.dispatch(URL, noProps())
End Sub


So lets analyze this script, first thing to see is divide this code into the different processes. Here we see 3 different subprocesses, first is CopySheet, SelectSheetByName and dispatchURL.
  • CopySheet - this is the logic of the script that will use the other two functions.
  • SelectSheetByName - this is just a function that will encapsulate the UNO components and put the parameters such as sheetname and getsheet.
  • dispatchURL - Also encapsulated uno method such as the URLTransformer to generate new documents and also the 'frame' object.


Having figure out this two functions is obvious we need to focus on the first sub process. First we need to get rid of the 'new document' and direct everything to the first document. So first thing was replacing the secondDoc with firstDoc so that there is no new document being created.

Second thing I did was playing around with the options on getByName into the actual sheet name. This was just for my specific document because I need specific names. The next was creating a loop.

This loop was a way to achieve a serialized number of copies, in the end my code look like this:
Sub CopySpreadsheet
  firstDoc = ThisComponent
  selectSheetByName(firstDoc, "Hoja1")
  dispatchURL(firstDoc,".uno:SelectAll")
  dispatchURL(firstDoc,".uno:Copy")
 for i = 1 To 14
  aNewSheetName = "Acceptance_Checklist_" & Format(i, "00")
  firstDoc.getSheets().insertNewByName(aNewSheetName,0)
  selectSheetByName(firstDoc, aNewSheetName)
  dispatchURL(firstDoc,".uno:Paste")
Next i
End Sub


I had to go several times into the book to get tips on how to build a loop. I even went to the OOoForum in order to get this question answered. Once it was answered, it was just logical processes. I got a loop on the aNewSheetName so that the label was Acceptance_Checklist and concatenated with the format(i, "00"), the i was the variable assigned by the For which continusly incremet the value of i until it reached 14.

The next line used the insertNew ByName function to generate that new sheet with the aNewSheetName label.

Finally we used the dispatchURL which use the UNO API to send the PASTE instruction.

The dispatcher is an interesting function because it let us send a command with less hassle. So instead of having to enumarte ALL the compoinents to get to the paste action we just need to call uno: PASTE. Same was done on Select and Copy early in that script.

Using a For enabled me to select a range, meaning that the sheet will be copied to a defined value which also protect the document from growing too big or crashing.

The script is not perfect however because the insertion takes place on a non-sequensial manner. That means the pages were inserted infront instead o the back of the list. This make me have a disjoined numeration such as:

109, 108, 107, 106.....4, 1, 2, 3


This clearly broke the order of the numeration, my guess is that this can be solved with a reverse loop.

on the next post I will talk about the label script to help me configure the content acording with the list of servers and how I got the datasource to connect with the script.

Managing Python extensions part II

, , , ...

This second part of Python extensions we will run some of the sample extensions in OpenOffice.org and how some of the more complex code happens in OOo. And how you can work it through.

First we will locate where the Python samples live in OpenOffice.org and how to get them to run in the OOo.

Running OOo Sample Macros
OpenOffice.org scripting framework support different languages, the menu also coordinate and manage different languages on different options. The Macros item located under Tools will give you options to record macros, execute macros as well as just view the macros acording to a specific language. This can be either:
  • OpenOffice.org BASIC
  • Python
  • Beanshell
  • Javascript
When you select any of this options you get a dialog that filter your macros by the language and just show you the language you got. Once you select the language you can just select the macros and click on execute.

If we want to select the HelloWorld.py we would do the following:
  1. Select Tools from the main menu
  2. Choose Macros and then decide what to choose
  3. You can select Execute macros and choose between the different macro languages
  4. Or select Organize Macros > Python and just choose between the python macros
  5. On any of the methods you will get a dialog and you will have 3 choices including: My Macros, OpenOffice.org Macros and the name of the file you are currently open.
  6. We want to select the OpenOffice.org Macros and you will see HelloWorld, choose it and u will expand it and display HelloWorldPython
  7. Once executed it will insert the legend Hello World (in Python) in your opendocument text.

You can experimenting running other samples:
  • Capitalize - This will change the capitalization of the text
  • MsgBox - This will open a dialog box which will ask for data and return one in exchange of the option
  • pythonSamples - TableSample - createTable - This will generate a document with text, headers and a rich format table populated with numbers and sum formula.

Editing OOo Macros
OpenOffice.org have different ways to edit the macros depending on the language. For OOoBasic OpenOffice.org includes an internal IDE which is in charge of editing the Macros.
For Javascript it uses the Rhyno Javascript Debugger, this debugger is brought from the mozilla community.

Finally the Beanshell scripts are also done with the Beanshell debugger, for more information check on the Openoffice.org website.

Finally our language for this session is Python, which doesn't has a native IDE and which scripting will not be able to edit within openoffice.org but on external editors. Please look on the previous blog entry to learn about how to install python scripts on OpenOffice.org.
November 2009
S M T W T F S
October 2009December 2009
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