<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.openoffice.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Iannz</id>
	<title>Apache OpenOffice Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.openoffice.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Iannz"/>
	<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/wiki/Special:Contributions/Iannz"/>
	<updated>2026-04-26T13:49:37Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.14</generator>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Bibliographic/Hints_and_Tips&amp;diff=34254</id>
		<title>Bibliographic/Hints and Tips</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Bibliographic/Hints_and_Tips&amp;diff=34254"/>
		<updated>2007-06-06T23:16:05Z</updated>

		<summary type="html">&lt;p&gt;Iannz: /* How to load Zotero reference data into Openoffice. */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Bibliographic_Project | Back to Bibliographic Index]]&lt;br /&gt;
==How do I preserve my Bibliographic Table format settings ?==&lt;br /&gt;
&lt;br /&gt;
When you have done all that hard work in setting up the bibliographic table with all the field entries and formatting set to your document style,  I suggest that you select and copy the Bibliographic table and save it in a other document. &lt;br /&gt;
&lt;br /&gt;
The reason I suggest this is that, if you accidentally delete the Bibliographic Table, then all your work in formatting the table will be deleted too. To use your Bibliographic Table formatting in an other document, just copy that table into new document, it does not matter that the references are different, just right click over the table and select &amp;#039;Update Index/Table&amp;#039; for it to be regenerated with that documents&amp;#039; citations and your previously defined Bibliographic Table format.&lt;br /&gt;
&lt;br /&gt;
==I edit my citations but the changes are not applied.==&lt;br /&gt;
&lt;br /&gt;
When you modify a citation (Bibliography Entry) by double-clicking on the citation, and selecting edit and modifying the entry. You also need to click on the &amp;#039;Modify&amp;#039; button to apply the changes before you select the &amp;#039;Close&amp;#039; button.&lt;br /&gt;
&lt;br /&gt;
==How do I correct the citations in my document?==&lt;br /&gt;
&lt;br /&gt;
If you have inserted a citation (Bibliography Entry) may times in a document and need to correct it. Correcting it in the database is not enough. The changes are NOT automatically made in the document. In fact each citation has complete copy of the citation data and must be correct for each citation. You have several options:&lt;br /&gt;
&lt;br /&gt;
1. Find each citation, delete it and reinsert it (after correcting it in the database). If you need to synchronize all your citations in the document with the ones in the database, you can use a keystroke macro recorder supporting auto-repitition of macros (e.g. [http://www.jitbit.com/macrorecorder.aspx JitBit Macro Recorder]). Record a macro for the &amp;quot;Insert Bibliography Entry&amp;quot; dialog to insert a single bibliography entry (and clicking &amp;quot;Yes&amp;quot;, if it ought to be updated), finishing with progressing to the next entry. This macro can then be applied in a repetitive manner to the dialog to synchronize all citations. However, note, that this way you may pollute your document by adding all bibliography entries from the database.&lt;br /&gt;
&lt;br /&gt;
2. Find each citation, double-clicking on the citation, select edit, make the corrections, close the edit panel, click the &amp;#039;Modify&amp;#039; button to apply the changes before you select &amp;#039;Close&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
3. If you have too many citations to change in this way then you can edit the save file. Make a backup of your file. Rename your xxx.odt file xxx.zip, open the zip archive and extract the contents.xml file, open that file in a writer. &amp;#039;&amp;#039;&amp;#039;Very carefully&amp;#039;&amp;#039;&amp;#039; do a global find and replace for your corrections. Save the contents.xml back into the zip archive. Rename xxx.zip xxx.odt. Hoping you have not destroyed your file, open it and check.&lt;br /&gt;
&lt;br /&gt;
==Having your bibliography index automatically numbered==&lt;br /&gt;
&lt;br /&gt;
To use numbered references like e.g. [1], which is common for scientific documents, you can change the formatting of the reference anchors / entries in the document by setting &amp;quot;Number entries&amp;quot; under Insert-&amp;gt;Index and Tables-&amp;gt;Index/Table. Your actual generated bibliography however will &amp;#039;&amp;#039;not&amp;#039;&amp;#039; be automatically numbered just by checking this field. This also cannot be activated in the &amp;quot;Entries&amp;quot; dialog (while the idea of inserting the &amp;quot;Number&amp;quot; Type in front of an entry looks tempting, this will not yield the correct result). Instead, you have to activate numbering on the corresponding bibliography style. In most cases this will be &amp;quot;Bibliography 1&amp;quot;. Activate &amp;quot;Numbering&amp;quot; on the Paragraph Style pane.&lt;br /&gt;
&lt;br /&gt;
== How can I Join multiple references? ==&lt;br /&gt;
&lt;br /&gt;
Is there any (automatic) way to coalesce multiple bibliographic references onto a single one? I mean, something like [1-3,56,99] instead of [1][2][3][56][99]. As far as I have seen, there is no option in OOo to do that.[[User:Andvaranaut|CP]] 19:40, 22 May 2006 (CEST)&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Answer&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
Yes, but not as automatically as you may like. There is an option in Inset-&amp;gt;Indexes and Tables-&amp;gt;Indexes and Tables:Type=Bibliography an option under the heading &amp;#039;Formatting the entries&amp;#039; a pick-list for &amp;#039;Brackets&amp;#039;. You can select NONE.&lt;br /&gt;
&lt;br /&gt;
If you select Brackets=NONE then [1][2][3][56][99] becomes 1 2 3 56 99 and you can then manually insert the brackets and the commas to get the desired [1,2,3,56,99]. However there is currently no automatic support for specifying a range of citations like [1-3]. The problem is that if you manually deleted the citation 2 and put in a dash, the  citation 2 may disappear from the Bibliography list if there are no other references to it. However, you could place  citation 2 in a &amp;#039;Hidden Paragraph&amp;#039; to ensure it stays in the Bibliography list for that document. See some [http://www.linuxjournal.com/node/9053/print instructions] on Hidden Paragraphs. [[User:Dnw|David Wilson]]&lt;br /&gt;
&lt;br /&gt;
==Converting footnotes to endnotes==&lt;br /&gt;
It is easy to convert footnotes on the same page to endnotes at the end of the document by changing the &amp;#039;Position&amp;#039; option on the Tools-&amp;gt;Foot&lt;br /&gt;
notes..-&amp;gt;Tab=Footnotes panel.&lt;br /&gt;
&lt;br /&gt;
However, if you do this, there is some good advice from Judith Butcher, &amp;#039;&amp;#039;Copy-Editing, The Cambridge Handbook&amp;#039;&amp;#039;, (Cambridge: CUP, 1975)-&lt;br /&gt;
&lt;br /&gt;
&amp;quot;More information may have to be given in the notes now that they will not appear on the same page as the relevant text. A book title and a page number - or just a publication place and date - may be sufficient in a footnote if the other details are mentioned in the text; but it is irritating to have to keep checking back to the text from the endnotes if one is looking through the notes for a book mentioned earlier.&amp;quot; p156&lt;br /&gt;
&lt;br /&gt;
==How can I import or export Bibliographic data?==&lt;br /&gt;
&lt;br /&gt;
[http://download.openoffice.org/2.0.4/index.html OpenOffice 2.0.4] Writer now includes a BibTeX export filter for citations in a document. You can access it at   &lt;br /&gt;
 File-&amp;gt;Export-&amp;gt;File Format=&amp;#039;Bibtex (.bib)&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
If you are using a earlier version of OpenOffice OpenOffice you can add it yourself - [http://www.math.umd.edu/~dcarrera/openoffice/misc/bibtex/filter.html bibtex export filter]. If you need to convert other bibliographic formats use  [[Bibliographic_Software_and_Standards_Information#Bibutils | bibutils]]. &lt;br /&gt;
&lt;br /&gt;
[[User:Dnw|David Wilson]] has written a bibliographic database filter to export the data in RIS  format [http://bibliographic.openoffice.org/files/documents/124/3781/OOoRSIExport-1.py OOoRISExport.py] &amp;lt;!-- RSI? --&amp;gt;. It is my first python program so is not very good but seems to work. See the wiki page [[OOoRISExport.py]] for details&lt;br /&gt;
&lt;br /&gt;
If you can download/export RIS (reference manager) format references from your data source, then the utility [http://bibliographic.openoffice.org/files/documents/124/3078/RISImport.py RISImport.py] may work better than a BibTeX utility. It is a Python script for importing RIS format reference(s), RISImport.py. Possibly of some value as it hashes out some RIS details on mapping between fields, and suggests &amp;quot;sensitive&amp;quot; mapping for different reference types.&amp;quot; For more hints see [[Bibliographic_Hints_and_Tips#How_to_load_Zotero_reference_data_into_Openoffice |How to load Zotero reference data into Openoffice]] below.&lt;br /&gt;
&lt;br /&gt;
If this is not suitable then an option is to use a third-party bibliographic application that will export to an OpenOffice Bibliographic database in the text bibliographic database CSV format. (OpenOffice looks for a database called Bibliography with the correct fields - it does not care what type of database it is.) I have used [[Bibliographic_Software_and_Standards_Information#JabRef | Jabref]] and [[Bibliographic_Software_and_Standards_Information#B3 | B3]]. [[Bibliographic_Software_and_Standards_Information#Bibus | Bibus]] is another possibility. [[User:Dnw|David Wilson]]&lt;br /&gt;
&lt;br /&gt;
You may also use [[Bibliographic_Software_and_Standards_Information#refbase | refbase]] to [http://openoffice.refbase.net/ export your references] directly to an OpenOffice Bibliographic database in OpenDocument spreadsheet (.ods) format.&lt;br /&gt;
&lt;br /&gt;
===Avoiding duplicate bibliographic records in the database===&lt;br /&gt;
&lt;br /&gt;
The RISImport.py bibliographic data import program does not check for duplicates. If there is more than one bibliographic database entry with the same identifier the OOo bibliographic functions will only find the first occurrence. To avoid this confusion I suggest that you modify your database table to add unique index using the identifier as a key. This will prevent the adding of duplicate entries. Instructions on how to do this and how to increase the size of the database fields can found in &lt;br /&gt;
[http://bibliographic.openoffice.org/files/documents/124/1284/HOWTO-increaseFieldSizes-V2.odt HOWTO-increaseFieldSizes-V2.odt]&lt;br /&gt;
&lt;br /&gt;
===Import from .odt-file===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Q:&amp;#039;&amp;#039;&amp;#039; I have an OOoWriter document containing large amount of citations and very big bibliographic table. Can I automatically add all bibliographic entries to my database? [[User:FLegmatik|fLegmatik]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;A:&amp;#039;&amp;#039;&amp;#039; There is no direct and simple mechanism. But there is a an indirect method - You can use the [http://www.math.umd.edu/~dcarrera/openoffice/misc/bibtex/filter.html bibtex export filter] mentioned below, to export the bibliographic data from you document. Then to import that BibTeX data into the database you could use the bibutils data conversion programs and method also described [[Bibliographic_Hints_and_Tips#How_to_use_Zotero_to_format_your_OOo_Bibliography | below]]. I have not tested this very well so I do not know how accurate the conversion process will be. [[User:Dnw|David Wilson]]&lt;br /&gt;
&lt;br /&gt;
===Importing bibtex (or other) formats to the Bibliography manager using JabRef===&lt;br /&gt;
&lt;br /&gt;
This was a better solution for me than the scripts mentioned below (since I am on a windows machine and couldn&amp;#039;t get them to work anyway).  This is described in the [http://jabref.sourceforge.net/help/OpenOfficeHelp.html JabRef documentation] (http://jabref.sourceforge.net/help/OpenOfficeHelp.html) and works well.  &amp;#039;&amp;#039;Note - I had a problem with exporting to the spreadsheet because of a random character having slipped into my bibtex file. If the export doesn&amp;#039;t work - check the records for wierd chars and delete them.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==How to load Zotero reference data into Openoffice.==&lt;br /&gt;
&lt;br /&gt;
[http://www.zotero.org zotero] [zoh-TAIR-oh] is a free, easy-to-use Firefox extension to help you collect, manage, and cite your research sources. It lives right where you do your work — in the web browser itself.&lt;br /&gt;
&lt;br /&gt;
As an alternative to the below approach an OOo extension is being developed. It currently works with the development branch for Zotero ([http://forums.zotero.org/discussion/640/development-xpi/]]). It is available from [https://www.zotero.org/trac/ticket/524]. Thanks to the University of Southern Queensland for financial assistance with this project.&lt;br /&gt;
&lt;br /&gt;
*Install  [http://bibliographic.openoffice.org/files/documents/124/3078/RISImport.py  RISmport.py] which reads RIS format files containing one or more references and inserts them into the default OpenOffice.org Bibliography/&amp;#039;biblio&amp;#039; database. [http://bibliographic.openoffice.org/files/documents/124/3077/RISImport_Instructions.odt instructions.odt] (Copy it into the /openoffice.org2.0/program/ directory)&lt;br /&gt;
*Select the Zotero titles you want to export to the OOo database&lt;br /&gt;
*Select Tools-&amp;gt;’Export Library’ (from the gear icon), select Format=RIS and save the temp.ris file.&lt;br /&gt;
*Start OpenOffice.org&lt;br /&gt;
*Import the RIS data using RISmport.py, with a command like:&lt;br /&gt;
 cd /openoffice.org2.0/program/python.sh  RISmport.py /your-path-to/temp.ris&lt;br /&gt;
*The reference details should now be in the default bibliographic database.&lt;br /&gt;
&lt;br /&gt;
To automate this a bit more, add a batch file to your path, called something like &amp;#039;import_ris&amp;#039;. This is the linux version, could someone add a windows version.&lt;br /&gt;
&lt;br /&gt;
 # import_ris calls RISImport.py to read a RIS file and&lt;br /&gt;
 # inserts the data into the OOo bibliographic database&lt;br /&gt;
 #!/bin/sh&lt;br /&gt;
 # put the path of your openoffice.org program directory on the next line.&lt;br /&gt;
 cd /opt/openoffice.org2.0/program&lt;br /&gt;
 echo &amp;quot;Importing RIS data from &amp;quot; $1&lt;br /&gt;
 echo&lt;br /&gt;
 ./python.sh  RISImport.py $1 &lt;br /&gt;
&lt;br /&gt;
To import BibTeX data I use [[Bibliographic_Software_and_Standards_Information#Bibutils |bibutils]] data conversion programs and the following script, import_bib  -&lt;br /&gt;
&lt;br /&gt;
 # import_bib calls uses bibutils to convert BibTex data to &lt;br /&gt;
 # RIS format and then call RISImport.py to read a RIS file and&lt;br /&gt;
 # inserts the data into the OOo bibliographic database&lt;br /&gt;
 # the bibutils programs bib2xml and xml2ris need to be in the &lt;br /&gt;
 # program search path&lt;br /&gt;
 #!/bin/sh&lt;br /&gt;
 cd /opt/openoffice.org2.0/program&lt;br /&gt;
 echo &amp;quot;importing BibTeX data from &amp;quot; $1&lt;br /&gt;
 echo&lt;br /&gt;
 bib2xml $1 | xml2ris &amp;gt; /tmp/bibtmp777&lt;br /&gt;
 ./python.sh  RISImport.py /tmp/bibtmp777&lt;br /&gt;
 rm /tmp/bibtmp777&lt;br /&gt;
&lt;br /&gt;
You can easily add COPAC, endnote, ISI web of science, Pubmed import as these are also supported by the bibutils data converter. Just replace the bib2xml in the script with copac2xml, end2xml, isi2xml or med2xml.&lt;br /&gt;
&lt;br /&gt;
If you are more adventurous and want to add this import function as menu items in Writer you could try loading these [[Bibliographic Import Macros | OOoBasic macros]].&lt;br /&gt;
&lt;br /&gt;
==How to use Zotero to format your OOo Bibliography==&lt;br /&gt;
&lt;br /&gt;
* If your version of OOo is less than 2.0.4, install the add-on module [http://www.hj-gym.dk/~hj/writer2latex/ writer2latex041] into OOo. (This export filter is included in [http://download.openoffice.org/2.0.4/index.html OOo 2.0.4]). It provides LateX and BibTeX export filters. The one we are interested in is the BibTeX export which exports the bibliographic data from the current document, (not the database), in BibteX format. (Instructions for installation on the web site).&lt;br /&gt;
*Open a OOo document with citations.&lt;br /&gt;
*Export your document bibliography data using: File-&amp;gt;Export-&amp;gt;File type=&amp;#039;BibTex Data File (.bib)&amp;#039; (i.e. temp.bib)&lt;br /&gt;
*In Zotero create a new Collection folder and select it.&lt;br /&gt;
*In Zotero import your temp.bib file by using the &amp;#039;gear&amp;#039; icon [[Image:gear-icon.png]] and Tools-&amp;gt;Import.&lt;br /&gt;
*Select all the titles you want to use for the bibliography (probably all the references you imported), right-click and select &amp;#039;Create Bibliography from Selected Items&amp;#039; from the context menu.&lt;br /&gt;
*Select the citation Style and &amp;#039;Copy to Clipboard&amp;#039; &lt;br /&gt;
*Paste bibliography text into your OOo document.&lt;br /&gt;
*Voila !&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Note: in my test the &amp;#039;Chicago Manual of Style (Note)&amp;#039; - a numbered reference list was not in the correct citation order.&lt;br /&gt;
&lt;br /&gt;
==How do I move my Bibliographic database==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data base file is called biblio.dbf and it is located on my linux system &lt;br /&gt;
in the directory:&lt;br /&gt;
&lt;br /&gt;
 ~/.openoffice.org2/user/database/biblio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
on Windows &lt;br /&gt;
&lt;br /&gt;
 C:\Program Files\OpenOffice.org x.x.x\presets\database&lt;br /&gt;
&lt;br /&gt;
So importing the bibliography is just a matter of copying the old biblio.dbf to the location of the new database. &lt;br /&gt;
&lt;br /&gt;
To change the location of the bibliographic database, first, understand that the bibliographic application looks for a database called &amp;#039;Bibliography&amp;#039; and a table called &amp;#039;biblio&amp;#039; in that database. (This is why it is easy to set up the bibliographic database on an other database sever, it does not matter if it mySQL or postgres or even a text file, it is the names &amp;#039;Bibliography&amp;#039; and &amp;#039;biblio&amp;#039; that matter.)&lt;br /&gt;
&lt;br /&gt;
In the case of the standard Xbase (.dbf) bibliographic database the &amp;quot;database&amp;quot; is actually a directory called /biblio and the &amp;quot;table&amp;quot; is a .dbf file in that directory called biblio.dbf&lt;br /&gt;
&lt;br /&gt;
You can change the location of the database by using the File-&amp;gt;New-&amp;gt;Database wizard. Create a new database called, say &amp;#039;Bibliography-new&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Then using the menu option-&lt;br /&gt;
&lt;br /&gt;
 Tools-&amp;gt;Options-&amp;gt;OpenOffice.org Base-&amp;gt;Database&lt;br /&gt;
&lt;br /&gt;
You should now have at least two databases listed, the original Bibliography and Bibliography-new. In that Panel edit the original Bibliography to change its name to &amp;#039;Bibliography-old&amp;#039; and change &amp;#039;Bibliography-new&amp;#039; to &amp;#039;Bibliography&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==I want a better thesaurus==&lt;br /&gt;
&lt;br /&gt;
The OpenOffice English language thesaurus is based on [http://wordnet.princeton.edu/ Wordnet].  The full Wordnet provides comprehensive information on word usage. Try it [http://wordnet.princeton.edu/perl/webwn online]&lt;br /&gt;
&lt;br /&gt;
Install wordnet and add a small shell script to set the  WNHOME and working directory and to pass on the selected word as a parameter (that is what the $1 does).&lt;br /&gt;
&lt;br /&gt;
 #!/bin/bash&lt;br /&gt;
 # a small script file called my_wnb at /home/dnw/my_wnb&lt;br /&gt;
 WNHOME=/usr/local/WordNet-2.1&lt;br /&gt;
 cd /usr/local/WordNet-2.1/bin&lt;br /&gt;
 /usr/local/WordNet-2.1/bin/wnb $1&lt;br /&gt;
&lt;br /&gt;
add the following OOBasic macro into OpenOffice, this macro selects the word the cursor is on and passes it to wordnet for a lookup.&lt;br /&gt;
&lt;br /&gt;
 Sub wordnet&lt;br /&gt;
 Dim sel As String &lt;br /&gt;
 Dim oSelect As object&lt;br /&gt;
    oSelect = thiscomponent.CurrentController.Selection&lt;br /&gt;
        for i = 0 to oSelect.getCount() - 1&lt;br /&gt;
                oRange = oSelect.getByIndex(i)&lt;br /&gt;
                sel =  oRange.String&lt;br /&gt;
        next i&lt;br /&gt;
 Shell(&amp;quot;/home/dnw/my_wnb&amp;quot;,1,sel) &lt;br /&gt;
 End Sub&lt;br /&gt;
&lt;br /&gt;
You can then assing the macro to a toolbar, shortcut-key or menu item.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Your question is not answered here ?==&lt;br /&gt;
Try the [[Bibliographic FAQ]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;I feel I am going around in circles and I can not find what I need.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
You could post add a question to this page or send a question to the Bibliographic Project user&amp;#039;s mail list at &lt;br /&gt;
[mailto://users@bibliographic.openoffice.org users@bibliographic.openoffice.org]&lt;br /&gt;
&lt;br /&gt;
==You are invited to add more Hints and Tips==&lt;br /&gt;
&lt;br /&gt;
Add a FAQ here or just ask a question on the [http://wiki.services.openoffice.org/mwiki/index.php?title=Talk:Bibliographic_Hints_and_Tips&amp;amp;action=edit discussion page]. [[User:Dnw|David Wilson]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Bibliographic]]&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Current_selection&amp;diff=27576</id>
		<title>Current selection</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Current_selection&amp;diff=27576"/>
		<updated>2007-03-12T02:24:29Z</updated>

		<summary type="html">&lt;p&gt;Iannz: Fixed link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;Current Selection in Text Documents&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Also see [[Extensions_development_basic]]. &lt;br /&gt;
&lt;br /&gt;
Having made sure that text is selected, it is common to create a loop to do something to all of the currently selected text. But, remember that the first element of the array is either the current selection when there is only one selection, or the insertion point when there is more than one selection. Thus the following common code: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oCurSelection = thisComponent.getCurrentSelection()&lt;br /&gt;
if oCurSelection.supportsService(&amp;quot;com.sun.star.text.TextRanges&amp;quot;) then&lt;br /&gt;
   nCount = oCurSelection.Count&lt;br /&gt;
   if nCount = 1 then&lt;br /&gt;
      oTextRange = oCurSelection.getByIndex(0)&lt;br /&gt;
      &amp;#039;Do some action on oTextRange&lt;br /&gt;
   else&lt;br /&gt;
      for i = 0 to nCount - 1&lt;br /&gt;
         oTextRange = oCurSelection.getByIndex(i)&lt;br /&gt;
         &amp;#039;Do some action on oTextRange&lt;br /&gt;
      next&lt;br /&gt;
   end if&lt;br /&gt;
end if&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Spreadsheet_common&amp;diff=11511</id>
		<title>Spreadsheet common</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Spreadsheet_common&amp;diff=11511"/>
		<updated>2006-05-31T23:10:23Z</updated>

		<summary type="html">&lt;p&gt;Iannz: Added example showing how to deal with multiple selections&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Common spreadsheet operations=&lt;br /&gt;
See also [[ working_with_documents]] &lt;br /&gt;
&lt;br /&gt;
==Current document==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Dim oDoc As Object&lt;br /&gt;
oDoc = ThisComponent&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Load existing document==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Dim oDoc As Object&lt;br /&gt;
oDoc = StartDesktop.loadComponentFromURL( ConvertToURL( &amp;quot;/home/robert/abc.xls&amp;quot; ), &amp;quot;_blank&amp;quot;, _&lt;br /&gt;
        0, Array() )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Document type check: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Function IsSpreadsheetDocument( oDoc As Object ) As Boolean&lt;br /&gt;
   IsSpreadsheetDocument = oDoc.supportsService( &amp;quot;com.sun.star.sheet.SpreadsheetDocument&amp;quot; )&lt;br /&gt;
End Function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Working with sheets=&lt;br /&gt;
&lt;br /&gt;
==Active sheet==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Function fnActiveSheet&lt;br /&gt;
ThisComponent.getCurrentController.getActiveSheet&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Number of sheets==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
thisComponent.getSheets.getCount&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get sheet by index==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Dim oSheet As Object&lt;br /&gt;
 &lt;br /&gt;
oSheet = thisComponent.getSheets.getByIndex( 0 )&lt;br /&gt;
&amp;#039; or in OOo BASIC&lt;br /&gt;
oSheet = oDoc.Sheets( 0 )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get sheet by name==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Dim oSheet As Object&lt;br /&gt;
 &lt;br /&gt;
oSheet = thisComponent.getSheets.getByName( &amp;quot;Sheet1&amp;quot; )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Iterate over all sheets==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039;iterate over all sheets&lt;br /&gt;
Dim oSheet As Object&lt;br /&gt;
Dim eSheets As Object&lt;br /&gt;
eSheets = oDoc.getSheets.createEnumeration&lt;br /&gt;
 &lt;br /&gt;
While eSheets.hasMoreElements&lt;br /&gt;
        oSheet = eSheets.nextElement()&lt;br /&gt;
 &lt;br /&gt;
        &amp;#039; here you can work your sheet&lt;br /&gt;
        MsgBox &amp;quot;Next sheet name is &amp;quot; &amp;amp; oSheet.getName &amp;amp; &amp;quot;.&amp;quot;&lt;br /&gt;
Wend&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create new sheet==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; create new sheet&lt;br /&gt;
oDoc = thisComponent&lt;br /&gt;
oSheet = oDoc.createInstance( &amp;quot;com.sun.star.sheet.Spreadsheet&amp;quot; )&lt;br /&gt;
oDoc.Sheets.insertByName( &amp;quot;new sheet&amp;quot;, oSheet )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Working with rows, columns=&lt;br /&gt;
&lt;br /&gt;
==Row, Column selection==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Dim oRow As Object&lt;br /&gt;
Dim oColumn As Object&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; get first row&lt;br /&gt;
oRow = oSheet.getRows.getByIndex( 0 )&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; get column B&lt;br /&gt;
oColumn = oSheet.getColumns.getByIndex( 1 )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Column Properties==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; column width (in 100ths of mm)&lt;br /&gt;
oColumn.setPropertyValue(&amp;quot;Width&amp;quot;, 100)&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; optimal width&lt;br /&gt;
oColumn.setPropertyValue(&amp;quot;OptimalWidth&amp;quot;, True)&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; hidden / visible&lt;br /&gt;
oColumn.setPropertyValue(&amp;quot;IsVisible&amp;quot;, False)&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; page break?&lt;br /&gt;
oColumn.setPropertyValue(&amp;quot;IsStartOfNewPage&amp;quot;, False)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Row properties==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; row height (in 100ths of mm)&lt;br /&gt;
oRow.setPropertyValue(&amp;quot;Height&amp;quot;, 100)&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; optimal height&lt;br /&gt;
oRow.setPropertyValue(&amp;quot;OptimalHeight&amp;quot;, True)&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; hidden / visible&lt;br /&gt;
oRow.setPropertyValue(&amp;quot;IsVisible&amp;quot;, False)&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; page break?&lt;br /&gt;
oRow.setPropertyValue(&amp;quot;IsStartOfNewPage&amp;quot;, False)&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Insert, delete row==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; insert 2 rows at the 4th position (still counting from 0)&lt;br /&gt;
oSheet.getRows.insertByIndex( 3, 2 )&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; remove 3 lines from the 7th line&lt;br /&gt;
oSheet.getRows.removeByIndex( 6, 3 )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Insert, delete column==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; insert 2 columns into the fourth (D) column&lt;br /&gt;
oSheet.getColumns.insertByIndex( 3, 2 )&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; remove 3 columns from the G column&lt;br /&gt;
oSheet.getColumns.removeByIndex( 6, 3 )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Working with cells=&lt;br /&gt;
&lt;br /&gt;
==Cell object==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Dim oCell As Object&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; select A1 (first number = column, second number = row)&lt;br /&gt;
oCell = oSheet.getCellByPosition( 0, 0 )&lt;br /&gt;
 &lt;br /&gt;
&amp;#039;Activecell (error check in case the current selection isn&amp;#039;t a cell)&lt;br /&gt;
on error resume next&lt;br /&gt;
oCell = ThisComponent.getCurrentSelection&lt;br /&gt;
 &lt;br /&gt;
&amp;#039;Get a named cell - in this case the name is &amp;quot;Date&amp;quot;&lt;br /&gt;
oCell = thisComponent.NamedRanges.getByName(&amp;quot;Date&amp;quot;).getReferredCells&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Each cell can contain text, number or formula: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; modify text&lt;br /&gt;
oCell.String = &amp;quot;This is A1 cell&amp;quot;&lt;br /&gt;
&amp;#039; Old form: oCell.setPropertyValue(&amp;quot;String&amp;quot;, &amp;quot;This is A1 cell&amp;quot; )&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; modify number&lt;br /&gt;
oCell.Value = 100&lt;br /&gt;
&amp;#039; Old form: oCell.setPropertyValue(&amp;quot;Value&amp;quot;, 100)&lt;br /&gt;
 &lt;br /&gt;
&amp;#039;Setting a cell to a fixed date and time (format the cell for date and/or time as desired)&lt;br /&gt;
oCell.Value = now&lt;br /&gt;
&amp;#039; Old form: oCell.setPropertyValue(&amp;quot;Value&amp;quot;, now)&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
&amp;#039; modify formula&lt;br /&gt;
oCell.Formula = &amp;quot;=A2+A3&amp;quot;&lt;br /&gt;
&amp;#039; Old form: oCell.setPropertyValue(&amp;quot;Formula&amp;quot;, &amp;quot;=A2+A3&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Content type detection==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Select Case oCell.Type&lt;br /&gt;
        Case com.sun.star.table.CellContentType.EMPTY&lt;br /&gt;
                &amp;#039; oCell is empty&lt;br /&gt;
 &lt;br /&gt;
        Case com.sun.star.table.CellContentType.VALUE&lt;br /&gt;
                &amp;#039; oCell contains number&lt;br /&gt;
 &lt;br /&gt;
        Case com.sun.star.table.CellContentType.TEXT&lt;br /&gt;
                &amp;#039; oCell contains string&lt;br /&gt;
 &lt;br /&gt;
        Case com.sun.star.table.CellContentType.FORMULA&lt;br /&gt;
                &amp;#039; oCell contains formula&lt;br /&gt;
End Select&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Cell range=&lt;br /&gt;
CellRangeAddress is a simple structure with five elements: &lt;br /&gt;
*Sheet &lt;br /&gt;
*StartColumn &lt;br /&gt;
*StartRow &lt;br /&gt;
*EndColumn &lt;br /&gt;
*EndRow &lt;br /&gt;
&lt;br /&gt;
CellRangeAddress is obviously used to modify more than one cell. &lt;br /&gt;
&lt;br /&gt;
==Insert cells==&lt;br /&gt;
Following example insert cells at B2:C3 range. Any existing values in the specified range are moved downwards. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Dim oRange As New com.sun.star.table.CellRangeAddress&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; first sheet and B2:C3 range&lt;br /&gt;
oRange.Sheet = 0&lt;br /&gt;
oRange.StartColumn = 1&lt;br /&gt;
oRange.StartRow = 1&lt;br /&gt;
oRange.EndColumn = 2&lt;br /&gt;
oRange.EndRow = 2&lt;br /&gt;
 &lt;br /&gt;
oSheet.insertCells( oRange, com.sun.star.sheet.CellInsertMode.DOWN )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Possible values for the second argument are: &lt;br /&gt;
*NONE &lt;br /&gt;
*DOWN the cells are moved downwards &lt;br /&gt;
*RIGHT the cells are moved to the right &lt;br /&gt;
*ROWS the rows are moved downwards &lt;br /&gt;
*COLUMNS the columns are moved to the right &lt;br /&gt;
&lt;br /&gt;
==Remove cells==&lt;br /&gt;
Following example remove cells at B2:C3 range. Any existing values in the specified range are moved upwards. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Dim oRange As New com.sun.star.table.CellRangeAddress&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; first sheet and B2:C3 range&lt;br /&gt;
oRange.Sheet = 0&lt;br /&gt;
oRange.StartColumn = 1&lt;br /&gt;
oRange.StartRow = 1&lt;br /&gt;
oRange.EndColumn = 2&lt;br /&gt;
oRange.EndRow = 2&lt;br /&gt;
 &lt;br /&gt;
oSheet.removeCells( oRange, com.sun.star.sheet.CellInsertMode.UP )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Possible values for the second argument are: &lt;br /&gt;
*NONE &lt;br /&gt;
*UP the cells are moved upwards &lt;br /&gt;
*LEFT the cells are moved to the left &lt;br /&gt;
*ROWS the rows are moved upwards &lt;br /&gt;
*COLUMNS the columns are moved to the left &lt;br /&gt;
&lt;br /&gt;
==Move, copy cells==&lt;br /&gt;
CellAddress is a new object, which will helps you identify the cell address and contains three elements: &lt;br /&gt;
&lt;br /&gt;
*Sheet &lt;br /&gt;
*Column &lt;br /&gt;
*Row &lt;br /&gt;
&lt;br /&gt;
Following example will move the A2:B3 cells to the A1. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oRange As New com.sun.star.table.CellRangeAddress&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; A2:B3 on the first sheet&lt;br /&gt;
oRange.Sheet = 0&lt;br /&gt;
oRange.StartColumn = 1&lt;br /&gt;
oRange.StartRow = 1&lt;br /&gt;
oRange.EndColumn = 2&lt;br /&gt;
oRange.EndRow = 2&lt;br /&gt;
 &lt;br /&gt;
Dim oAddress As New com.sun.star.table.CellAddress&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; A1 on the first sheet&lt;br /&gt;
oAddress.Sheet = 0&lt;br /&gt;
oAddress.Column = 0&lt;br /&gt;
oAddress.Row = 0&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; move the selected range to new position&lt;br /&gt;
oSheet.moveRange( oAddress, oRange )&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; copy the selected range to new position&lt;br /&gt;
oSheet.copyRange( oAddress, oRange )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Range selection by name==&lt;br /&gt;
You can create range address with cell names: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oRange = oSheet.getCellRangeByName( &amp;quot;B2:C3&amp;quot; )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
You can select cells from the range in the same way as from the sheet. Following example returns cell B2: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oCell = oRange.getCellByPosition( 0, 0 )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The cell position is counted from the upper left corner of the range, not of the sheet. &lt;br /&gt;
&lt;br /&gt;
==Content deletion==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Dim nFlags As Long&lt;br /&gt;
 &lt;br /&gt;
oRange = oSheet.getCellRangeByName( &amp;quot;B2:C3&amp;quot; )&lt;br /&gt;
 &lt;br /&gt;
nFlags = com.sun.star.sheet.CellFlags.STRING + _&lt;br /&gt;
        com.sun.star.sheet.CellFlags.STYLES&lt;br /&gt;
 &lt;br /&gt;
oRange.clearContents( nFlags )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Available flags listed below: &lt;br /&gt;
&lt;br /&gt;
*VALUE numerical value &lt;br /&gt;
*DATETIME date or time &lt;br /&gt;
*STRING strings &lt;br /&gt;
*ANNOTATION comments &lt;br /&gt;
*FORMULA formulas &lt;br /&gt;
*HARDATTR direct formatting of cells &lt;br /&gt;
*STYLES indirect formatting &lt;br /&gt;
*OBJECTS drawing objects connected to cells &lt;br /&gt;
*EDITATTR formatting that applies to parts of the cells &lt;br /&gt;
&lt;br /&gt;
=Formatting=&lt;br /&gt;
The following examples can be applied to either a Cell or a RangeAddress. &lt;br /&gt;
&lt;br /&gt;
See [[working_with_styles#number_formats]] for information on changing number formats. &lt;br /&gt;
&lt;br /&gt;
==Background color, shadows==&lt;br /&gt;
Shadow is defined in the structure com.sun.star.table.ShadowFormat, which has four elements. &lt;br /&gt;
&lt;br /&gt;
*Color shadow color &lt;br /&gt;
*Location shadow location &lt;br /&gt;
*ShadowWidth shadow width &lt;br /&gt;
*IsTransparent shadow transparency &lt;br /&gt;
&lt;br /&gt;
Possible values for Location are: &lt;br /&gt;
*NONE &lt;br /&gt;
*TOP_LEFT &lt;br /&gt;
*TOP_RIGHT &lt;br /&gt;
*BOTTOM_LEFT &lt;br /&gt;
*BOTTOM_RIGHT &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; cell background color&lt;br /&gt;
oCell.setPropertyValue( &amp;quot;CellBackColor&amp;quot;, RGB( 0, 0, 0 ) )&lt;br /&gt;
        &lt;br /&gt;
&amp;#039; cell background transparency&lt;br /&gt;
oCell.setPropertyValue( &amp;quot;IsCellBackgroundTransparent&amp;quot;, False )&lt;br /&gt;
        &lt;br /&gt;
&amp;#039; cell shadow&lt;br /&gt;
Dim oShadow As New com.sun.star.table.ShadowFormat&lt;br /&gt;
        &lt;br /&gt;
oShadow.Location = com.sun.star.table.ShadowLocation.BOTTOM_RIGHT&lt;br /&gt;
oShadow.Color = RGB(255, 255, 0)&lt;br /&gt;
oShadow.ShadowWidth = 50&lt;br /&gt;
oShadow.IsTransparent = False&lt;br /&gt;
        &lt;br /&gt;
oCell.setPropertyValue( &amp;quot;ShadowFormat&amp;quot;, oShadow )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Justification==&lt;br /&gt;
&lt;br /&gt;
===Horizontal===&lt;br /&gt;
Each cell contains property HoriJustify with possible values (com.sun.star.table.CellHoriJustify): &lt;br /&gt;
*STANDARD &lt;br /&gt;
*LEFT &lt;br /&gt;
*CENTER &lt;br /&gt;
*RIGHT &lt;br /&gt;
*BLOCK &lt;br /&gt;
*REPEAT &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; horizontal justification - right&lt;br /&gt;
oCell.setPropertyValue( &amp;quot;HoriJustify&amp;quot;, com.sun.star.table.CellHoriJustify.RIGHT )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Vertical===&lt;br /&gt;
Each cell contains property VertJustify with possible values (com.sun.star.table.CellVertJustify): &lt;br /&gt;
*STANDARD &lt;br /&gt;
*TOP &lt;br /&gt;
*CENTER &lt;br /&gt;
*BOTTOM &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; vertical justification - center&lt;br /&gt;
oCell.setPropertyValue( &amp;quot;VertJustify&amp;quot;, com.sun.star.table.CellVertJustify.CENTER )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Orientation===&lt;br /&gt;
Each cell contains property Orientation with possible values (com.sun.star.table.CellOrientation): &lt;br /&gt;
*STANDARD &lt;br /&gt;
*TOPBOTTOM &lt;br /&gt;
*BOTTOMTOP &lt;br /&gt;
*STACKED &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; orientation - STACKED&lt;br /&gt;
oCell.setPropertyValue( &amp;quot;Orientation&amp;quot;, com.sun.star.table.CellOrientation.STACKED )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Wrapping, rotation===&lt;br /&gt;
Each cell contains property IsTextWrapped (Boolean) and RotateAngle (Long) for better justification. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; wrapped text&lt;br /&gt;
oCell.setPropertyValue( &amp;quot;IsTextWrapped&amp;quot;, True )&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; vertical text&lt;br /&gt;
oCell.setPropertyValue( &amp;quot;RotateAngle&amp;quot;, 90 )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Example: Setting currently selected cells to current date and time=&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub subSetDate&lt;br /&gt;
oDoc = thisComponent&lt;br /&gt;
oSelection = oDoc.getCurrentSelection&lt;br /&gt;
nFormat = fnGetNumberFormatId(oDoc,&amp;quot;DD/MM/YY&amp;quot;)&lt;br /&gt;
if HasUnoInterfaces(oSelection, &amp;quot;com.sun.star.lang.XServiceInfo&amp;quot;) then&lt;br /&gt;
	if oSelection.supportsService(&amp;quot;com.sun.star.sheet.SheetCellRanges&amp;quot;) then&lt;br /&gt;
		&amp;#039;More than one range selected&lt;br /&gt;
		subSetRanges(oSelection, vValue, nFormat)&lt;br /&gt;
	elseif oSelection.supportsService(&amp;quot;com.sun.star.table.CellRange&amp;quot;) then&lt;br /&gt;
		&amp;#039;Only one range but more than one cell&lt;br /&gt;
		subSetRange(oSelection, now, nFormat)&lt;br /&gt;
	elseif oSelection.supportsService(&amp;quot;com.sun.star.sheet.SheetCell&amp;quot;) then&lt;br /&gt;
		&amp;#039;only one cell selected&lt;br /&gt;
		subSetCell(oSelection, now, nFormat)	&lt;br /&gt;
	end if&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
sub subSetRanges(oRanges, vValue, nFormat)&lt;br /&gt;
for i = 0 to oRanges.getCount -1&lt;br /&gt;
	subSetRange(oRanges.getByIndex(i), vValue, nFormat)&lt;br /&gt;
next&lt;br /&gt;
end sub&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
sub subSetRange(oRange, vValue, nFormat)&lt;br /&gt;
for i = 0 to oRange.getColumns.getCount - 1&lt;br /&gt;
	for j = 0 to oRange.getRows.getCount - 1&lt;br /&gt;
		subSetCell(oRange.getCellByPosition(i,j), vValue, nFormat)&lt;br /&gt;
	next&lt;br /&gt;
next&lt;br /&gt;
end sub&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
sub subSetCell(oCell, vValue, nFormat)&lt;br /&gt;
oCell.value=vValue&lt;br /&gt;
oCell.setPropertyValue(&amp;quot;NumberFormat&amp;quot;, nFormat)&lt;br /&gt;
end sub&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fnGetNumberFormatId(oDoc, sNumberFormat)&lt;br /&gt;
sCharLocale = oDoc.getPropertyValue(&amp;quot;CharLocale&amp;quot;)&lt;br /&gt;
nFormatId = oDoc.getNumberFormats.queryKey(sNumberFormat, sCharLocale, false)&lt;br /&gt;
if nFormatId = -1 then &amp;#039;Not yet defined&lt;br /&gt;
        nFormatId = oDoc.getNumberFormats.addNew(sNumberFormat, sCharLocale)&lt;br /&gt;
end if&lt;br /&gt;
fnGetNumberFormatId = nFormatId&lt;br /&gt;
end function &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Basic:Tutorials]]&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=CookBook&amp;diff=9376</id>
		<title>CookBook</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=CookBook&amp;diff=9376"/>
		<updated>2006-05-02T01:51:57Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The material in this tutorial style cookbook builds upon the material covered in [[Extensions_development_basic|Starting in Basic]]. &lt;br /&gt;
&lt;br /&gt;
=General Guides=&lt;br /&gt;
[[Working with documents]] &lt;br /&gt;
&lt;br /&gt;
[[Working with properties]] &lt;br /&gt;
&lt;br /&gt;
[[Sorting and searching]] &lt;br /&gt;
&lt;br /&gt;
[[Working with styles]] &lt;br /&gt;
&lt;br /&gt;
=Component specific guides=&lt;br /&gt;
[[Working with Text Documents]] &lt;br /&gt;
&lt;br /&gt;
[[Working with Spreadsheets]]&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=UNO_component_packaging&amp;diff=9375</id>
		<title>UNO component packaging</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=UNO_component_packaging&amp;diff=9375"/>
		<updated>2006-05-02T01:41:30Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Python UNO component=&lt;br /&gt;
This page shows you how to pack and deploy already written UNO component. I&amp;#039;m using my &amp;#039;&amp;#039;Wavelet&amp;#039;&amp;#039; class as an example of a very simple component. &lt;br /&gt;
&lt;br /&gt;
More detailed info is in the [[http://api.openoffice.org/docs/DevelopersGuide/Components/Components.htm Developers Guide]]. &lt;br /&gt;
&lt;br /&gt;
=Python loader=&lt;br /&gt;
Python loader is not able load classes from more than one file. Thus it&amp;#039;s necessary to put all classes in one python source file. (Honestly, I read it somewhere and I didn&amp;#039;t test this.) &lt;br /&gt;
&lt;br /&gt;
=Sample Python component=&lt;br /&gt;
&lt;br /&gt;
==Wavelet class==&lt;br /&gt;
We will use my sample &amp;#039;&amp;#039;Wavelet&amp;#039;&amp;#039; class which replaces space with non breaking space before the Czech prepositions. Put the following code in the &amp;#039;&amp;#039;Wavelet.py&amp;#039;&amp;#039; file. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[python]&lt;br /&gt;
import uno&lt;br /&gt;
import unohelper&lt;br /&gt;
import string&lt;br /&gt;
 &lt;br /&gt;
from com.sun.star.task import XJobExecutor&lt;br /&gt;
 &lt;br /&gt;
class Wavelet( unohelper.Base, XJobExecutor ):&lt;br /&gt;
    def __init__( self, ctx ):&lt;br /&gt;
        self.ctx = ctx&lt;br /&gt;
 &lt;br /&gt;
    def trigger( self, args ):&lt;br /&gt;
        desktop = self.ctx.ServiceManager.createInstanceWithContext(&lt;br /&gt;
            &amp;quot;com.sun.star.frame.Desktop&amp;quot;, self.ctx )&lt;br /&gt;
 &lt;br /&gt;
        doc = desktop.getCurrentComponent()&lt;br /&gt;
 &lt;br /&gt;
        try:&lt;br /&gt;
            search = doc.createSearchDescriptor()&lt;br /&gt;
            search.SearchRegularExpression = True&lt;br /&gt;
            search.SearchString = &amp;quot;\\&amp;lt;(k|s|v|z|o|u|i|a) &amp;quot;&lt;br /&gt;
            &lt;br /&gt;
            found = doc.findFirst( search )&lt;br /&gt;
            while found:&lt;br /&gt;
                found.String = string.replace( found.String, &amp;quot; &amp;quot;, u&amp;quot;\xa0&amp;quot; )&lt;br /&gt;
                found = doc.findNext( found.End, search)&lt;br /&gt;
 &lt;br /&gt;
        except:&lt;br /&gt;
            pass&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Wavelet class registration==&lt;br /&gt;
You have to tell the OpenOffice.org what is the main class of your component. Put the following code at the end of your &amp;#039;&amp;#039;Wavelet.py&amp;#039;&amp;#039; file. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[python]&lt;br /&gt;
g_ImplementationHelper = unohelper.ImplementationHelper()&lt;br /&gt;
g_ImplementationHelper.addImplementation(&lt;br /&gt;
        Wavelet,&lt;br /&gt;
        &amp;quot;name.vojta.openoffice.Wavelet&amp;quot;,&lt;br /&gt;
        (&amp;quot;com.sun.star.task.Job&amp;quot;,),)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Component integration=&lt;br /&gt;
&lt;br /&gt;
==Icons==&lt;br /&gt;
You can create your own icons for the Menu item or the Toolbar button. The easiest way is to create two true color BMP files - the first one should be 26×26 and the second one should be 16×16. &lt;br /&gt;
&lt;br /&gt;
If you want to use alpha (transparent color), use &amp;#039;&amp;#039;#FF00FF&amp;#039;&amp;#039; (RGB) color. &lt;br /&gt;
&lt;br /&gt;
This possibility is optional and you&amp;#039;re not forced to create icons. &lt;br /&gt;
&lt;br /&gt;
==Addons.xcu==&lt;br /&gt;
Component integration configuration is in the &amp;#039;&amp;#039;Addons.xcu&amp;#039;&amp;#039; file. &lt;br /&gt;
&lt;br /&gt;
===Header===&lt;br /&gt;
The header of this file should contain: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[xml]&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&amp;lt;oor:component-data xmlns:oor=&amp;quot;http://openoffice.org/2001/registry&amp;quot;&lt;br /&gt;
  xmlns:xs=&amp;quot;http://www.w3.org/2001/XMLSchema&amp;quot; oor:name=&amp;quot;Addons&amp;quot;&lt;br /&gt;
  oor:package=&amp;quot;org.openoffice.Office&amp;quot;&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;node oor:name=&amp;quot;AddonUI&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Office Menu Bar===&lt;br /&gt;
Following part creates new menu item &amp;#039;&amp;#039;Czech&amp;#039;&amp;#039; (or &amp;#039;&amp;#039;Cestina&amp;#039;&amp;#039;, depends on the UI language) and the &amp;#039;&amp;#039;Wavelet&amp;#039;&amp;#039; menu item. &lt;br /&gt;
&lt;br /&gt;
This menu item is associated with the &amp;#039;&amp;#039;name.vojta.openoffice.Wavelet?execute&amp;#039;&amp;#039; &amp;#039;&amp;#039;URL&amp;#039;&amp;#039;. It means, that when you click on the menuitem, &amp;#039;&amp;#039;Wavelet.trigger&amp;#039;&amp;#039; method will be executed with the &amp;#039;&amp;#039;execute&amp;#039;&amp;#039; as an argument. &lt;br /&gt;
&lt;br /&gt;
This menu will be visible in the OpenOffice.org Writer only. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[xml]&lt;br /&gt;
        &amp;lt;node oor:name=&amp;quot;OfficeMenuBar&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;node oor:name=&amp;quot;name.vojta.openoffice.Wavelet&amp;quot; oor:op=&amp;quot;replace&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;prop oor:name=&amp;quot;Title&amp;quot; oor:type=&amp;quot;xs:string&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;value/&amp;gt;&lt;br /&gt;
                    &amp;lt;value xml:lang=&amp;quot;en-US&amp;quot;&amp;gt;Czech&amp;lt;/value&amp;gt;&lt;br /&gt;
                    &amp;lt;value xml:lang=&amp;quot;cs&amp;quot;&amp;gt;Cestina&amp;lt;/value&amp;gt;&lt;br /&gt;
                &amp;lt;/prop&amp;gt;&lt;br /&gt;
                &amp;lt;prop oor:name=&amp;quot;Target&amp;quot; oor:type=&amp;quot;xs:string&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;value&amp;gt;_self&amp;lt;/value&amp;gt;&lt;br /&gt;
                &amp;lt;/prop&amp;gt;&lt;br /&gt;
                &amp;lt;prop oor:name=&amp;quot;ImageIdentifier&amp;quot; oor:type=&amp;quot;xs:string&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;value/&amp;gt;&lt;br /&gt;
                &amp;lt;/prop&amp;gt;&lt;br /&gt;
                &amp;lt;node oor:name=&amp;quot;Submenu&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;node oor:name=&amp;quot;m1&amp;quot; oor:op=&amp;quot;replace&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;prop oor:name=&amp;quot;URL&amp;quot; oor:type=&amp;quot;xs:string&amp;quot;&amp;gt;&lt;br /&gt;
                            &amp;lt;value&amp;gt;service:name.vojta.openoffice.Wavelet?execute&amp;lt;/value&amp;gt;&lt;br /&gt;
                        &amp;lt;/prop&amp;gt;&lt;br /&gt;
                        &amp;lt;prop oor:name=&amp;quot;Title&amp;quot; oor:type=&amp;quot;xs:string&amp;quot;&amp;gt;&lt;br /&gt;
                            &amp;lt;value/&amp;gt;&lt;br /&gt;
                            &amp;lt;value xml:lang=&amp;quot;en-US&amp;quot;&amp;gt;Wavelet&amp;lt;/value&amp;gt;&lt;br /&gt;
                            &amp;lt;value xml:lang=&amp;quot;cs&amp;quot;&amp;gt;Vlnka&amp;lt;/value&amp;gt;&lt;br /&gt;
                        &amp;lt;/prop&amp;gt;&lt;br /&gt;
                        &amp;lt;prop oor:name=&amp;quot;Target&amp;quot; oor:type=&amp;quot;xs:string&amp;quot;&amp;gt;&lt;br /&gt;
                            &amp;lt;value&amp;gt;_self&amp;lt;/value&amp;gt;&lt;br /&gt;
                        &amp;lt;/prop&amp;gt;&lt;br /&gt;
                        &amp;lt;prop oor:name=&amp;quot;Context&amp;quot; oor:type=&amp;quot;xs:string&amp;quot;&amp;gt;&lt;br /&gt;
                            &amp;lt;value&amp;gt;com.sun.star.text.TextDocument&amp;lt;/value&amp;gt;&lt;br /&gt;
                        &amp;lt;/prop&amp;gt;&lt;br /&gt;
                    &amp;lt;/node&amp;gt;&lt;br /&gt;
                &amp;lt;/node&amp;gt;&lt;br /&gt;
            &amp;lt;/node&amp;gt;&lt;br /&gt;
        &amp;lt;/node&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Office Toolbar===&lt;br /&gt;
Following part creates new toolbar (with name &amp;#039;&amp;#039;Add-on 1&amp;#039;&amp;#039;, &amp;#039;&amp;#039;Add-on 2&amp;#039;&amp;#039;, …) and one button. This button is associated with the &amp;#039;&amp;#039;name.vojta.openoffice.Wavelet?execute&amp;#039;&amp;#039; &amp;#039;&amp;#039;URL&amp;#039;&amp;#039;. It means that the &amp;#039;&amp;#039;Wavelet.trigger&amp;#039;&amp;#039; method will be executed when you click on the button on the toolbar. &amp;#039;&amp;#039;execute&amp;#039;&amp;#039; will be passed as an argument. &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039; You can&amp;#039;t rename the toolbar. It&amp;#039;s due to the backwards compatibility with the 1.1.x version. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[xml]&lt;br /&gt;
        &amp;lt;node oor:name=&amp;quot;OfficeToolBar&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;node oor:name=&amp;quot;name.vojta.openoffice.Wavelet&amp;quot; oor:op=&amp;quot;replace&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;node oor:name=&amp;quot;m1&amp;quot; oor:op=&amp;quot;replace&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;prop oor:name=&amp;quot;URL&amp;quot; oor:type=&amp;quot;xs:string&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;value&amp;gt;service:name.vojta.openoffice.Wavelet?execute&amp;lt;/value&amp;gt;&lt;br /&gt;
                    &amp;lt;/prop&amp;gt;&lt;br /&gt;
                    &amp;lt;prop oor:name=&amp;quot;ImageIdentifier&amp;quot; oor:type=&amp;quot;xs:string&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;value/&amp;gt;&lt;br /&gt;
                    &amp;lt;/prop&amp;gt;&lt;br /&gt;
                    &amp;lt;prop oor:name=&amp;quot;Title&amp;quot; oor:type=&amp;quot;xs:string&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;value/&amp;gt;&lt;br /&gt;
                        &amp;lt;value xml:lang=&amp;quot;en-US&amp;quot;&amp;gt;Wavelet&amp;lt;/value&amp;gt;&lt;br /&gt;
                        &amp;lt;value xml:lang=&amp;quot;cs&amp;quot;&amp;gt;Vlnka&amp;lt;/value&amp;gt;&lt;br /&gt;
                    &amp;lt;/prop&amp;gt;&lt;br /&gt;
                    &amp;lt;prop oor:name=&amp;quot;Target&amp;quot; oor:type=&amp;quot;xs:string&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;value&amp;gt;_self&amp;lt;/value&amp;gt;&lt;br /&gt;
                    &amp;lt;/prop&amp;gt;&lt;br /&gt;
                    &amp;lt;prop oor:name=&amp;quot;Context&amp;quot; oor:type=&amp;quot;xs:string&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;value&amp;gt;com.sun.star.text.TextDocument&amp;lt;/value&amp;gt;&lt;br /&gt;
                    &amp;lt;/prop&amp;gt;&lt;br /&gt;
                &amp;lt;/node&amp;gt;&lt;br /&gt;
            &amp;lt;/node&amp;gt;&lt;br /&gt;
        &amp;lt;/node&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Icons===&lt;br /&gt;
You can associate your icons with any &amp;#039;&amp;#039;URL&amp;#039;&amp;#039;. We will associate our icons with &amp;#039;&amp;#039;name.vojta.openoffice.Wavelet?execute&amp;#039;&amp;#039; &amp;#039;&amp;#039;URL&amp;#039;&amp;#039;. It means that all controls (menu item, button, …) associated with the same &amp;#039;&amp;#039;URL&amp;#039;&amp;#039; will use these icons. &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039; %origin% is the UNO component package. We will explain it later. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[xml]&lt;br /&gt;
        &amp;lt;node oor:name=&amp;quot;Images&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;node oor:name=&amp;quot;name.vojta.openoffice.Wavelet.image1&amp;quot; oor:op=&amp;quot;replace&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;prop oor:name=&amp;quot;URL&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;value&amp;gt;service:name.vojta.openoffice.Wavelet?execute&amp;lt;/value&amp;gt;&lt;br /&gt;
                &amp;lt;/prop&amp;gt;&lt;br /&gt;
                &amp;lt;node oor:name=&amp;quot;UserDefinedImages&amp;quot;&amp;gt;&lt;br /&gt;
                    &amp;lt;prop oor:name=&amp;quot;ImageSmallURL&amp;quot; oor:type=&amp;quot;xs:string&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;value&amp;gt;%origin%/images/WaveletSmall.bmp&amp;lt;/value&amp;gt;&lt;br /&gt;
                    &amp;lt;/prop&amp;gt;&lt;br /&gt;
                    &amp;lt;prop oor:name=&amp;quot;ImageBigURL&amp;quot; oor:type=&amp;quot;xs:string&amp;quot;&amp;gt;&lt;br /&gt;
                        &amp;lt;value&amp;gt;%origin%/images/WaveletBig.bmp&amp;lt;/value&amp;gt;&lt;br /&gt;
                    &amp;lt;/prop&amp;gt;&lt;br /&gt;
                &amp;lt;/node&amp;gt;&lt;br /&gt;
            &amp;lt;/node&amp;gt;&lt;br /&gt;
        &amp;lt;/node&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Footer===&lt;br /&gt;
Close all opened sections. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[xml]&lt;br /&gt;
    &amp;lt;/node&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;/oor:component-data&amp;gt;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=UNO component package=&lt;br /&gt;
UNO component package is a simple ZIP file. Obviously it contains the &amp;#039;&amp;#039;Addons.xcu&amp;#039;&amp;#039; file, &amp;#039;&amp;#039;images&amp;#039;&amp;#039; directory with icons and the Python component implementation. &lt;br /&gt;
&lt;br /&gt;
==Packing==&lt;br /&gt;
You can pack our sample package with the following command: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[shell]&lt;br /&gt;
zip -r Wavelet.uno.zip Addons.xcu Wavelet.py images&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The final &amp;#039;&amp;#039;Wavelet.uno.zip&amp;#039;&amp;#039; package should contain these files: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[shell]&lt;br /&gt;
Wavelet.uno.zip&lt;br /&gt;
  Addons.xcu&lt;br /&gt;
  Wavelet.py&lt;br /&gt;
  images/WaveletBig.bmp&lt;br /&gt;
  images/WaveletSmall.bmp&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039; The &amp;#039;&amp;#039;%origin%&amp;#039;&amp;#039; is &amp;#039;&amp;#039;Wavelet.uno.zip&amp;#039;&amp;#039;, thus the &amp;#039;&amp;#039;%origin%/images/WaveletBig.bmp&amp;#039;&amp;#039; points to the &amp;#039;&amp;#039;WaveletBig.bmp&amp;#039;&amp;#039; file in your &amp;#039;&amp;#039;Wavelet.uno.zip&amp;#039;&amp;#039; file. &lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
You can install your UNO component with the package manager (somewhere in the &amp;#039;&amp;#039;Tools&amp;#039;&amp;#039; menu) or with the &amp;#039;&amp;#039;unopkg&amp;#039;&amp;#039; tool. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[shell]&lt;br /&gt;
/opt/openoffice.org1.9.103/program/unopkg add Wavelet.uno.zip&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Uninstallation==&lt;br /&gt;
You can uninstall your UNO component with the package manager (somewhere in the &amp;#039;&amp;#039;Tools&amp;#039;&amp;#039; menu) or with the &amp;#039;&amp;#039;unopkg&amp;#039;&amp;#039; tool. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[shell]&lt;br /&gt;
/opt/openoffice.org1.9.103/program/unopkg remove Wavelet.uno.zip&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Python component testing=&lt;br /&gt;
It&amp;#039;s not necessary to install the Python UNO component to test it. You can connect to the running OpenOffice.org instance and test your UNO component directly. &lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
Append the following code at the end of the &amp;#039;&amp;#039;Wavelet.py&amp;#039;&amp;#039; file. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[python]&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    import os&lt;br /&gt;
 &lt;br /&gt;
    # Start OpenOffice.org, listen for connections and open testing document&lt;br /&gt;
    os.system( &amp;quot;/etc/openoffice.org-1.9/program/soffice &amp;#039;-accept=socket,host=localhost,port=2002;urp;&amp;#039; -writer ./WaveletTest.odt &amp;amp;&amp;quot; )&lt;br /&gt;
 &lt;br /&gt;
    # Get local context info&lt;br /&gt;
    localContext = uno.getComponentContext()&lt;br /&gt;
    resolver = localContext.ServiceManager.createInstanceWithContext(&lt;br /&gt;
        &amp;quot;com.sun.star.bridge.UnoUrlResolver&amp;quot;, localContext )&lt;br /&gt;
 &lt;br /&gt;
    ctx = None&lt;br /&gt;
 &lt;br /&gt;
    # Wait until the OO.o starts and connection is established&lt;br /&gt;
    while ctx == None:&lt;br /&gt;
        try:&lt;br /&gt;
            ctx = resolver.resolve(&lt;br /&gt;
                &amp;quot;uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext&amp;quot; )&lt;br /&gt;
        except:&lt;br /&gt;
            pass&lt;br /&gt;
 &lt;br /&gt;
    # Trigger our job&lt;br /&gt;
    wavelet = Wavelet( ctx )&lt;br /&gt;
    wavelet.trigger( () )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Testing==&lt;br /&gt;
To test your UNO component, just run your &amp;#039;&amp;#039;Wavelet.py&amp;#039;&amp;#039; in the Python interpreter. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[shell]&lt;br /&gt;
/opt/openoffice.org1.9.103/program/python ./Wavelet.py&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Resume==&lt;br /&gt;
This part does this: &lt;br /&gt;
&lt;br /&gt;
starts OpenOffice.org and opens the &amp;#039;&amp;#039;WaveletTest.odt&amp;#039;&amp;#039; file &lt;br /&gt;
&lt;br /&gt;
loop until the connection will be established &lt;br /&gt;
&lt;br /&gt;
start your component in the running OpenOffice.org context &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039; Do not forget to remove this part before real UNO component packaging. Or comment it out.&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Python&amp;diff=9374</id>
		<title>Python</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Python&amp;diff=9374"/>
		<updated>2006-05-02T01:33:15Z</updated>

		<summary type="html">&lt;p&gt;Iannz: /* Ressources */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Extensions}}&lt;br /&gt;
=== Python specific information for Extension creation ===&lt;br /&gt;
&lt;br /&gt;
=== Ressources ===&lt;br /&gt;
* [http://udk.openoffice.org/python/scriptingframework/index.html Python as a macro language in OpenOffice.org 2.x]&lt;br /&gt;
* [http://udk.openoffice.org/python/python-bridge.html pyUNO bridge]&lt;br /&gt;
* [http://blogs.nuxeo.com/sections/blogs/laurent_godard/2006_04_13_testing-pyuno-programs-with-doctests Introduction on testing pyUNO programs with doctests]&lt;br /&gt;
*[[UNO component packaging]]&lt;br /&gt;
[[Category:Extensions]]&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Custom_functions&amp;diff=9373</id>
		<title>Custom functions</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Custom_functions&amp;diff=9373"/>
		<updated>2006-05-02T01:29:01Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Simple functions=&lt;br /&gt;
&lt;br /&gt;
==Cell as an argument==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Function Cube( c1 )&lt;br /&gt;
    Cube = c1 * c1 * c1&lt;br /&gt;
End Function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
You can put &amp;#039;&amp;#039;=Cube(A1)&amp;#039;&amp;#039; in any cell. &lt;br /&gt;
&lt;br /&gt;
==More cells as the arguments==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Function SimpleSum( c1, c2 )&lt;br /&gt;
    SimpleSum = c1 + c2&lt;br /&gt;
End Function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
You can put &amp;#039;&amp;#039;=SimpleSum(A1;A2)&amp;#039;&amp;#039; in any cell. &lt;br /&gt;
&lt;br /&gt;
==Cells range as an argument==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Function MySum( oRange As Variant )&lt;br /&gt;
If Not IsArray( oRange ) Then&lt;br /&gt;
        If IsNumeric( oRange ) Then&lt;br /&gt;
                MySum = oRange&lt;br /&gt;
        else&lt;br /&gt;
                MySum = 0&lt;br /&gt;
        End If&lt;br /&gt;
        Exit Function&lt;br /&gt;
End If&lt;br /&gt;
 &lt;br /&gt;
Dim nSum As double&lt;br /&gt;
 &lt;br /&gt;
nSum = 0&lt;br /&gt;
 &lt;br /&gt;
For i = 1 To ubound( oRange, 1 )&lt;br /&gt;
        For j = 1 To ubound( oRange, 2 )&lt;br /&gt;
 &lt;br /&gt;
                If IsNumeric( oRange( i, j ) ) Then&lt;br /&gt;
                        nSum = nSum + oRange( i, j )            &lt;br /&gt;
                End If&lt;br /&gt;
        Next j&lt;br /&gt;
Next i&lt;br /&gt;
 &lt;br /&gt;
MySum = nSum&lt;br /&gt;
End Function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
You can put &amp;#039;&amp;#039;=MySum(A1:A3)&amp;#039;&amp;#039; in any cell. &lt;br /&gt;
&lt;br /&gt;
It is not possible to write to custom function that uses a cell range that spans sheets. E.g. &amp;lt;tt&amp;gt;=Sheet1.A2:Sheet2.A2&amp;lt;/tt&amp;gt; instead you would have to have separate parameters for each sheet.&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Data_pilots&amp;diff=9372</id>
		<title>Data pilots</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Data_pilots&amp;diff=9372"/>
		<updated>2006-05-02T01:23:15Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The last I looked it was not possible to access a DataPilot based on external data via the API - so these routines are for DataPilots based on data within the spreadsheet.&lt;br /&gt;
&lt;br /&gt;
=Current data pilot=&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Function fnCurDataPilot(oCursor as object) as object&lt;br /&gt;
 &lt;br /&gt;
&amp;#039;Returns the first data pilot that intersects with oCursor&lt;br /&gt;
&amp;#039;If no data pilot intersects it returns null&lt;br /&gt;
 &lt;br /&gt;
dim oEnum as object,  oDP as object&lt;br /&gt;
 &lt;br /&gt;
oEnum = thisComponent.getCurrentController.getActiveSheet.getDataPilotTables.createEnumeration&lt;br /&gt;
While oEnum.hasMoreElements()&lt;br /&gt;
        oDP = oEnum.nextElement()&lt;br /&gt;
        if oCursor.queryIntersection(oDP.outputRange).getCount &amp;gt; 0 then&lt;br /&gt;
                fnCurDataPilot = oDp&lt;br /&gt;
                exit function&lt;br /&gt;
        end if&lt;br /&gt;
wend&lt;br /&gt;
&amp;#039;fnCurDataPilot = null&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Example of calling the above function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = thisComponent&lt;br /&gt;
oCurSelection = oDoc.CurrentSelection&lt;br /&gt;
oSheet = oDoc.CurrentController.ActiveSheet&lt;br /&gt;
oCursor = oSheet.createCursorbyRange(oCurSelection)&lt;br /&gt;
oDataPilot = fnCurDataPilot(oCursor)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Delete datapilot=&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub subDeleteDataPilot(oDoc, oDataPilot)&lt;br /&gt;
oDoc.getsheets.getByIndex(oDataPilot.getOutputRange.sheet).getDataPilotTables.removeByName(oDataPilot.Name)&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Calc/API/Dialogs&amp;diff=9371</id>
		<title>Calc/API/Dialogs</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Calc/API/Dialogs&amp;diff=9371"/>
		<updated>2006-05-02T01:19:59Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;For general information on creating dialogs see the OOo on line help for create dialog.. &lt;br /&gt;
&lt;br /&gt;
A common task when presenting a dialog in a spreadsheet is to request a cell range. The following routines allow a user to select a cell range. Unfortunately, the user has to click a button to activate the routines (i.e. still to do is a routine to activate these routines when the user clicks outside the dialog). &lt;br /&gt;
&lt;br /&gt;
The dialog has the following requirements: &lt;br /&gt;
*A button or buttons with Initiate event set to subEventShrink &lt;br /&gt;
*The above button(s) have the tag field set to the name of the corresponding text field &lt;br /&gt;
*For each button a corresponding text field for the range address &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; The dialog is kept in a global variable so that other subroutines can access it (below).&lt;br /&gt;
Private oDialog As Object&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; oDestField is kept in a global variable so that it is available to the the range selection listener&lt;br /&gt;
&amp;#039; routine, and it knows which edit box is the destination for the selection string.&lt;br /&gt;
private oDestField as object&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; bSelecting is the variable whose value gets changed so that a loop can be exited when selecting a range&lt;br /&gt;
&amp;#039; has finished.&lt;br /&gt;
private bSelecting as boolean&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; This variable is so that the dialog can be endExecuted under program control, so that the range selection listener &lt;br /&gt;
&amp;#039; will work under both Windows and Linux, and reactivated when required.&lt;br /&gt;
private bDialogFinished as boolean&lt;br /&gt;
 &lt;br /&gt;
Sub Main()&lt;br /&gt;
&amp;#039; Make sure this library, with its dialog is loaded.&lt;br /&gt;
DialogLibraries.LoadLibrary( &amp;quot;SignificantDigits&amp;quot; )&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; Create the dialog object.&lt;br /&gt;
oDialog = createUnoDialog( DialogLibraries.GetByName( &amp;quot;SignificantDigits&amp;quot; ).GetByName( &amp;quot;SigDigitsDlg&amp;quot; ) )&lt;br /&gt;
 &lt;br /&gt;
&amp;#039;Other code for setting up the dialog goes here&lt;br /&gt;
        &lt;br /&gt;
&amp;#039; Display the dialog.&lt;br /&gt;
&amp;#039; This routine call does not return until the dialog is dismissed.&lt;br /&gt;
 &lt;br /&gt;
do&lt;br /&gt;
   bDialogFinished = true&lt;br /&gt;
   oDialog.Execute()&lt;br /&gt;
loop until bDialogFinished      &lt;br /&gt;
&amp;#039; Execution does not reach this point until the dialog is dismissed.&lt;br /&gt;
End Sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
&amp;#039;The following routines for range selection were improved (actually made to work)&lt;br /&gt;
&amp;#039;with input from Jim Thompson and with concepts in a thread by Danad:&lt;br /&gt;
&amp;#039;http://www.oooforum.org/forum/viewtopic.php?t=6160&lt;br /&gt;
 &lt;br /&gt;
sub subEventShrink (oEvent)&lt;br /&gt;
&amp;#039;Called when Rng button clicked&lt;br /&gt;
&amp;#039;Uses module variables: oDialog, oRangeSelectionListener, oDestRange&lt;br /&gt;
dim mRangeSelection, sField as string&lt;br /&gt;
 &lt;br /&gt;
sField =  oEvent.source.model.tag&lt;br /&gt;
oDestField = oDialog.getControl(sField)&lt;br /&gt;
subAddPropertyValue( mRangeSelection, &amp;quot;InitialValue&amp;quot;, oDestField.text)&lt;br /&gt;
subAddPropertyValue( mRangeSelection, &amp;quot;Title&amp;quot;, oDialog.title &amp;amp; &amp;quot; &amp;quot; &amp;amp; sField )&lt;br /&gt;
subAddPropertyValue( mRangeSelection, &amp;quot;CloseOnMouseRelease&amp;quot;, true )&lt;br /&gt;
 &lt;br /&gt;
&amp;#039;The order of starting the range selection and hiding the dialog is important it must be as follows&lt;br /&gt;
oDocCtrl = thisComponent.getCurrentController()&lt;br /&gt;
 &lt;br /&gt;
oRangeSelectionListener = CreateUnoListener( &amp;quot;RangeSelectionListener_&amp;quot;,&amp;quot;com.sun.star.sheet.XRangeSelectionListener&amp;quot; )&lt;br /&gt;
oDocCtrl.addRangeSelectionListener( oRangeSelectionListener ) &amp;#039; Register the listener&lt;br /&gt;
bSelecting = true&lt;br /&gt;
bDialogFinished = false&lt;br /&gt;
oDialog.endExecute&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
oDocCtrl.startRangeSelection(mRangeSelection )&lt;br /&gt;
while bSelecting&lt;br /&gt;
wend&lt;br /&gt;
oDocCtrl.removeRangeSelectionListener(oRangeSelectionListener)&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
Sub RangeSelectionListener_done(oRangeSelectionEvent as new com.sun.star.sheet.RangeSelectionEvent)&lt;br /&gt;
&amp;#039;Uses module variables: bSelecting, oRangeSelectionEvent, oDestField, oDialog&lt;br /&gt;
&amp;#039;Called when the range selection is done (clicking the icon at right end)&lt;br /&gt;
 &lt;br /&gt;
oDestField.text= oRangeSelectionEvent.RangeDescriptor&lt;br /&gt;
bSelecting = false&lt;br /&gt;
&amp;#039;oDialog.visible=true&lt;br /&gt;
&amp;#039;oDialog.enable = true&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
Sub RangeSelectionListener_aborted(oRangeSelectionEvent as new com.sun.star.sheet.RangeSelectionEvent)&lt;br /&gt;
&amp;#039;Uses module variables: bSelecting, oDialog&lt;br /&gt;
&amp;#039;Called when the range selection is cancelled (clicking X at top right)&lt;br /&gt;
bSelecting = false&lt;br /&gt;
&amp;#039;oDialog.visible=true&lt;br /&gt;
&amp;#039;oDialog.enable = true&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
Sub RangeSelectionListener_disposing()&lt;br /&gt;
&amp;#039;nothing to do&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a working example see: [[http://homepages.paradise.net.nz/hillview/OOo/SignificantDigits-2004-12-19-17.sxc| significantdigits]].&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Spreadsheet_common&amp;diff=9370</id>
		<title>Spreadsheet common</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Spreadsheet_common&amp;diff=9370"/>
		<updated>2006-05-02T01:10:38Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Common spreadsheet operations=&lt;br /&gt;
See also [[ working_with_documents]] &lt;br /&gt;
&lt;br /&gt;
==Current document==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Dim oDoc As Object&lt;br /&gt;
oDoc = ThisComponent&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Load existing document==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Dim oDoc As Object&lt;br /&gt;
oDoc = StartDesktop.loadComponentFromURL( ConvertToURL( &amp;quot;/home/robert/abc.xls&amp;quot; ), &amp;quot;_blank&amp;quot;, _&lt;br /&gt;
        0, Array() )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Document type check: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Function IsSpreadsheetDocument( oDoc As Object ) As Boolean&lt;br /&gt;
   IsSpreadsheetDocument = oDoc.supportsService( &amp;quot;com.sun.star.sheet.SpreadsheetDocument&amp;quot; )&lt;br /&gt;
End Function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Working with sheets=&lt;br /&gt;
&lt;br /&gt;
==Active sheet==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Function fnActiveSheet&lt;br /&gt;
ThisComponent.getCurrentController.getActiveSheet&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Number of sheets==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
thisComponent.getSheets.getCount&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get sheet by index==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Dim oSheet As Object&lt;br /&gt;
 &lt;br /&gt;
oSheet = thisComponent.getSheets.getByIndex( 0 )&lt;br /&gt;
&amp;#039; or in OOo BASIC&lt;br /&gt;
oSheet = oDoc.Sheets( 0 )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Get sheet by name==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Dim oSheet As Object&lt;br /&gt;
 &lt;br /&gt;
oSheet = thisComponent.getSheets.getByName( &amp;quot;Sheet1&amp;quot; )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Iterate over all sheets==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039;iterate over all sheets&lt;br /&gt;
Dim oSheet As Object&lt;br /&gt;
Dim eSheets As Object&lt;br /&gt;
eSheets = oDoc.getSheets.createEnumeration&lt;br /&gt;
 &lt;br /&gt;
While eSheets.hasMoreElements&lt;br /&gt;
        oSheet = eSheets.nextElement()&lt;br /&gt;
 &lt;br /&gt;
        &amp;#039; here you can work your sheet&lt;br /&gt;
        MsgBox &amp;quot;Next sheet name is &amp;quot; &amp;amp; oSheet.getName &amp;amp; &amp;quot;.&amp;quot;&lt;br /&gt;
Wend&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Create new sheet==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; create new sheet&lt;br /&gt;
oDoc = thisComponent&lt;br /&gt;
oSheet = oDoc.createInstance( &amp;quot;com.sun.star.sheet.Spreadsheet&amp;quot; )&lt;br /&gt;
oDoc.Sheets.insertByName( &amp;quot;new sheet&amp;quot;, oSheet )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Working with rows, columns=&lt;br /&gt;
&lt;br /&gt;
==Row, Column selection==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Dim oRow As Object&lt;br /&gt;
Dim oColumn As Object&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; get first row&lt;br /&gt;
oRow = oSheet.getRows.getByIndex( 0 )&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; get column B&lt;br /&gt;
oColumn = oSheet.getColumns.getByIndex( 1 )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Column Properties==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; column width (in 100ths of mm)&lt;br /&gt;
oColumn.setPropertyValue(&amp;quot;Width&amp;quot;, 100)&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; optimal width&lt;br /&gt;
oColumn.setPropertyValue(&amp;quot;OptimalWidth&amp;quot;, True)&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; hidden / visible&lt;br /&gt;
oColumn.setPropertyValue(&amp;quot;IsVisible&amp;quot;, False)&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; page break?&lt;br /&gt;
oColumn.setPropertyValue(&amp;quot;IsStartOfNewPage&amp;quot;, False)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Row properties==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; row height (in 100ths of mm)&lt;br /&gt;
oRow.setPropertyValue(&amp;quot;Height&amp;quot;, 100)&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; optimal height&lt;br /&gt;
oRow.setPropertyValue(&amp;quot;OptimalHeight&amp;quot;, True)&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; hidden / visible&lt;br /&gt;
oRow.setPropertyValue(&amp;quot;IsVisible&amp;quot;, False)&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; page break?&lt;br /&gt;
oRow.setPropertyValue(&amp;quot;IsStartOfNewPage&amp;quot;, False)&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Insert, delete row==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; insert 2 rows at the 4th position (still counting from 0)&lt;br /&gt;
oSheet.getRows.insertByIndex( 3, 2 )&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; remove 3 lines from the 7th line&lt;br /&gt;
oSheet.getRows.removeByIndex( 6, 3 )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Insert, delete column==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; insert 2 columns into the fourth (D) column&lt;br /&gt;
oSheet.getColumns.insertByIndex( 3, 2 )&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; remove 3 columns from the G column&lt;br /&gt;
oSheet.getColumns.removeByIndex( 6, 3 )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Working with cells=&lt;br /&gt;
&lt;br /&gt;
==Cell object==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Dim oCell As Object&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; select A1 (first number = column, second number = row)&lt;br /&gt;
oCell = oSheet.getCellByPosition( 0, 0 )&lt;br /&gt;
 &lt;br /&gt;
&amp;#039;Activecell (error check in case the current selection isn&amp;#039;t a cell)&lt;br /&gt;
on error resume next&lt;br /&gt;
oCell = ThisComponent.getCurrentSelection&lt;br /&gt;
 &lt;br /&gt;
&amp;#039;Get a named cell - in this case the name is &amp;quot;Date&amp;quot;&lt;br /&gt;
oCell = thisComponent.NamedRanges.getByName(&amp;quot;Date&amp;quot;).getReferredCells&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Each cell can contain text, number or formula: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; modify text&lt;br /&gt;
oCell.String = &amp;quot;This is A1 cell&amp;quot;&lt;br /&gt;
&amp;#039; Old form: oCell.setPropertyValue(&amp;quot;String&amp;quot;, &amp;quot;This is A1 cell&amp;quot; )&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; modify number&lt;br /&gt;
oCell.Value = 100&lt;br /&gt;
&amp;#039; Old form: oCell.setPropertyValue(&amp;quot;Value&amp;quot;, 100)&lt;br /&gt;
 &lt;br /&gt;
&amp;#039;Setting a cell to a fixed date and time (format the cell for date and/or time as desired)&lt;br /&gt;
oCell.Value = now&lt;br /&gt;
&amp;#039; Old form: oCell.setPropertyValue(&amp;quot;Value&amp;quot;, now)&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
&amp;#039; modify formula&lt;br /&gt;
oCell.Formula = &amp;quot;=A2+A3&amp;quot;&lt;br /&gt;
&amp;#039; Old form: oCell.setPropertyValue(&amp;quot;Formula&amp;quot;, &amp;quot;=A2+A3&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Content type detection==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Select Case oCell.Type&lt;br /&gt;
        Case com.sun.star.table.CellContentType.EMPTY&lt;br /&gt;
                &amp;#039; oCell is empty&lt;br /&gt;
 &lt;br /&gt;
        Case com.sun.star.table.CellContentType.VALUE&lt;br /&gt;
                &amp;#039; oCell contains number&lt;br /&gt;
 &lt;br /&gt;
        Case com.sun.star.table.CellContentType.TEXT&lt;br /&gt;
                &amp;#039; oCell contains string&lt;br /&gt;
 &lt;br /&gt;
        Case com.sun.star.table.CellContentType.FORMULA&lt;br /&gt;
                &amp;#039; oCell contains formula&lt;br /&gt;
End Select&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Cell range=&lt;br /&gt;
CellRangeAddress is a simple structure with five elements: &lt;br /&gt;
*Sheet &lt;br /&gt;
*StartColumn &lt;br /&gt;
*StartRow &lt;br /&gt;
*EndColumn &lt;br /&gt;
*EndRow &lt;br /&gt;
&lt;br /&gt;
CellRangeAddress is obviously used to modify more than one cell. &lt;br /&gt;
&lt;br /&gt;
==Insert cells==&lt;br /&gt;
Following example insert cells at B2:C3 range. Any existing values in the specified range are moved downwards. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Dim oRange As New com.sun.star.table.CellRangeAddress&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; first sheet and B2:C3 range&lt;br /&gt;
oRange.Sheet = 0&lt;br /&gt;
oRange.StartColumn = 1&lt;br /&gt;
oRange.StartRow = 1&lt;br /&gt;
oRange.EndColumn = 2&lt;br /&gt;
oRange.EndRow = 2&lt;br /&gt;
 &lt;br /&gt;
oSheet.insertCells( oRange, com.sun.star.sheet.CellInsertMode.DOWN )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Possible values for the second argument are: &lt;br /&gt;
*NONE &lt;br /&gt;
*DOWN the cells are moved downwards &lt;br /&gt;
*RIGHT the cells are moved to the right &lt;br /&gt;
*ROWS the rows are moved downwards &lt;br /&gt;
*COLUMNS the columns are moved to the right &lt;br /&gt;
&lt;br /&gt;
==Remove cells==&lt;br /&gt;
Following example remove cells at B2:C3 range. Any existing values in the specified range are moved upwards. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Dim oRange As New com.sun.star.table.CellRangeAddress&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; first sheet and B2:C3 range&lt;br /&gt;
oRange.Sheet = 0&lt;br /&gt;
oRange.StartColumn = 1&lt;br /&gt;
oRange.StartRow = 1&lt;br /&gt;
oRange.EndColumn = 2&lt;br /&gt;
oRange.EndRow = 2&lt;br /&gt;
 &lt;br /&gt;
oSheet.removeCells( oRange, com.sun.star.sheet.CellInsertMode.UP )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Possible values for the second argument are: &lt;br /&gt;
*NONE &lt;br /&gt;
*UP the cells are moved upwards &lt;br /&gt;
*LEFT the cells are moved to the left &lt;br /&gt;
*ROWS the rows are moved upwards &lt;br /&gt;
*COLUMNS the columns are moved to the left &lt;br /&gt;
&lt;br /&gt;
==Move, copy cells==&lt;br /&gt;
CellAddress is a new object, which will helps you identify the cell address and contains three elements: &lt;br /&gt;
&lt;br /&gt;
*Sheet &lt;br /&gt;
*Column &lt;br /&gt;
*Row &lt;br /&gt;
&lt;br /&gt;
Following example will move the A2:B3 cells to the A1. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oRange As New com.sun.star.table.CellRangeAddress&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; A2:B3 on the first sheet&lt;br /&gt;
oRange.Sheet = 0&lt;br /&gt;
oRange.StartColumn = 1&lt;br /&gt;
oRange.StartRow = 1&lt;br /&gt;
oRange.EndColumn = 2&lt;br /&gt;
oRange.EndRow = 2&lt;br /&gt;
 &lt;br /&gt;
Dim oAddress As New com.sun.star.table.CellAddress&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; A1 on the first sheet&lt;br /&gt;
oAddress.Sheet = 0&lt;br /&gt;
oAddress.Column = 0&lt;br /&gt;
oAddress.Row = 0&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; move the selected range to new position&lt;br /&gt;
oSheet.moveRange( oAddress, oRange )&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; copy the selected range to new position&lt;br /&gt;
oSheet.copyRange( oAddress, oRange )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Range selection by name==&lt;br /&gt;
You can create range address with cell names: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oRange = oSheet.getCellRangeByName( &amp;quot;B2:C3&amp;quot; )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
You can select cells from the range in the same way as from the sheet. Following example returns cell B2: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oCell = oRange.getCellByPosition( 0, 0 )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The cell position is counted from the upper left corner of the range, not of the sheet. &lt;br /&gt;
&lt;br /&gt;
==Content deletion==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Dim nFlags As Long&lt;br /&gt;
 &lt;br /&gt;
oRange = oSheet.getCellRangeByName( &amp;quot;B2:C3&amp;quot; )&lt;br /&gt;
 &lt;br /&gt;
nFlags = com.sun.star.sheet.CellFlags.STRING + _&lt;br /&gt;
        com.sun.star.sheet.CellFlags.STYLES&lt;br /&gt;
 &lt;br /&gt;
oRange.clearContents( nFlags )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Available flags listed below: &lt;br /&gt;
&lt;br /&gt;
*VALUE numerical value &lt;br /&gt;
*DATETIME date or time &lt;br /&gt;
*STRING strings &lt;br /&gt;
*ANNOTATION comments &lt;br /&gt;
*FORMULA formulas &lt;br /&gt;
*HARDATTR direct formatting of cells &lt;br /&gt;
*STYLES indirect formatting &lt;br /&gt;
*OBJECTS drawing objects connected to cells &lt;br /&gt;
*EDITATTR formatting that applies to parts of the cells &lt;br /&gt;
&lt;br /&gt;
=Formatting=&lt;br /&gt;
The following examples can be applied to either a Cell or a RangeAddress. &lt;br /&gt;
&lt;br /&gt;
See [[working_with_styles#number_formats]] for information on changing number formats. &lt;br /&gt;
&lt;br /&gt;
==Background color, shadows==&lt;br /&gt;
Shadow is defined in the structure com.sun.star.table.ShadowFormat, which has four elements. &lt;br /&gt;
&lt;br /&gt;
*Color shadow color &lt;br /&gt;
*Location shadow location &lt;br /&gt;
*ShadowWidth shadow width &lt;br /&gt;
*IsTransparent shadow transparency &lt;br /&gt;
&lt;br /&gt;
Possible values for Location are: &lt;br /&gt;
*NONE &lt;br /&gt;
*TOP_LEFT &lt;br /&gt;
*TOP_RIGHT &lt;br /&gt;
*BOTTOM_LEFT &lt;br /&gt;
*BOTTOM_RIGHT &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; cell background color&lt;br /&gt;
oCell.setPropertyValue( &amp;quot;CellBackColor&amp;quot;, RGB( 0, 0, 0 ) )&lt;br /&gt;
        &lt;br /&gt;
&amp;#039; cell background transparency&lt;br /&gt;
oCell.setPropertyValue( &amp;quot;IsCellBackgroundTransparent&amp;quot;, False )&lt;br /&gt;
        &lt;br /&gt;
&amp;#039; cell shadow&lt;br /&gt;
Dim oShadow As New com.sun.star.table.ShadowFormat&lt;br /&gt;
        &lt;br /&gt;
oShadow.Location = com.sun.star.table.ShadowLocation.BOTTOM_RIGHT&lt;br /&gt;
oShadow.Color = RGB(255, 255, 0)&lt;br /&gt;
oShadow.ShadowWidth = 50&lt;br /&gt;
oShadow.IsTransparent = False&lt;br /&gt;
        &lt;br /&gt;
oCell.setPropertyValue( &amp;quot;ShadowFormat&amp;quot;, oShadow )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Justification==&lt;br /&gt;
&lt;br /&gt;
===Horizontal===&lt;br /&gt;
Each cell contains property HoriJustify with possible values (com.sun.star.table.CellHoriJustify): &lt;br /&gt;
*STANDARD &lt;br /&gt;
*LEFT &lt;br /&gt;
*CENTER &lt;br /&gt;
*RIGHT &lt;br /&gt;
*BLOCK &lt;br /&gt;
*REPEAT &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; horizontal justification - right&lt;br /&gt;
oCell.setPropertyValue( &amp;quot;HoriJustify&amp;quot;, com.sun.star.table.CellHoriJustify.RIGHT )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Vertical===&lt;br /&gt;
Each cell contains property VertJustify with possible values (com.sun.star.table.CellVertJustify): &lt;br /&gt;
*STANDARD &lt;br /&gt;
*TOP &lt;br /&gt;
*CENTER &lt;br /&gt;
*BOTTOM &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; vertical justification - center&lt;br /&gt;
oCell.setPropertyValue( &amp;quot;VertJustify&amp;quot;, com.sun.star.table.CellVertJustify.CENTER )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Orientation===&lt;br /&gt;
Each cell contains property Orientation with possible values (com.sun.star.table.CellOrientation): &lt;br /&gt;
*STANDARD &lt;br /&gt;
*TOPBOTTOM &lt;br /&gt;
*BOTTOMTOP &lt;br /&gt;
*STACKED &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; orientation - STACKED&lt;br /&gt;
oCell.setPropertyValue( &amp;quot;Orientation&amp;quot;, com.sun.star.table.CellOrientation.STACKED )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Wrapping, rotation===&lt;br /&gt;
Each cell contains property IsTextWrapped (Boolean) and RotateAngle (Long) for better justification. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; wrapped text&lt;br /&gt;
oCell.setPropertyValue( &amp;quot;IsTextWrapped&amp;quot;, True )&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; vertical text&lt;br /&gt;
oCell.setPropertyValue( &amp;quot;RotateAngle&amp;quot;, 90 )&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Working_with_Spreadsheets&amp;diff=9369</id>
		<title>Working with Spreadsheets</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Working_with_Spreadsheets&amp;diff=9369"/>
		<updated>2006-05-02T00:54:21Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Spreadsheet common|Working with spreadsheet documents, sheets, rows, columns, cells, ranges, formatting]]&lt;br /&gt;
&lt;br /&gt;
[[Spreadsheet dialogs]]&lt;br /&gt;
&lt;br /&gt;
[[Data pilots]]&lt;br /&gt;
&lt;br /&gt;
[[Custom functions]]&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Writer/API/TextRange&amp;diff=9368</id>
		<title>Writer/API/TextRange</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Writer/API/TextRange&amp;diff=9368"/>
		<updated>2006-05-02T00:51:47Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;Working with Text Ranges&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
The [[ Current selection]], the [[ View cursor]] and not visible [[ Text cursor]]s all provide the [[ TextRange]] service. &lt;br /&gt;
&lt;br /&gt;
As does &amp;lt;tt&amp;gt;thisComponent.text&amp;lt;/tt&amp;gt;, and to make life more incestous text portion enumerations. &lt;br /&gt;
&lt;br /&gt;
It is this service which provides the methods and properties for changing the text. &lt;br /&gt;
&lt;br /&gt;
=Inserting text=&lt;br /&gt;
Inserting text is accomplished with the method &amp;lt;tt&amp;gt;insertString&amp;lt;/tt&amp;gt;. The parameters to this function are the location in the text range to insert the string at, the string itself, and whether the text at the specified location gets replaced. &lt;br /&gt;
&lt;br /&gt;
The following routine inserts text at the view cursor. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub subInsertString(oDoc, sString, bReplace)&lt;br /&gt;
oVC = oDoc.getCurrentController.getViewCursor&lt;br /&gt;
oText = oVC.text&lt;br /&gt;
oText.insertString(oVC, sString, bReplace)&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The following example inserts the text &amp;quot;Some sample text&amp;quot; to the left of the current selection, leaving the orginal selection still selected. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
subInsertString(thisComponent, &amp;quot;Some sample text&amp;quot;, false)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Inserting control codes=&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub subInsertParagraphMarker(oDoc)&lt;br /&gt;
oVC = oDoc.getCurrentController.getViewCursor&lt;br /&gt;
oText = oVC.text&lt;br /&gt;
oText.insertControlCharacter(oVC, com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK, False)&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The control codes are: &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|0&lt;br /&gt;
|com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK&lt;br /&gt;
|This control character starts a new paragraph.&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|com.sun.star.text.ControlCharacter.LINE_BREAK&lt;br /&gt;
|This control character starts a new line in a paragraph.&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|com.sun.star.text.ControlCharacter.HARD_HYPHEN&lt;br /&gt;
|This control character equals a dash but prevents this position from being hyphenated.&lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|com.sun.star.text.ControlCharacter.SOFT_HYPHEN&lt;br /&gt;
|This control character defines a special position as a hyphenation point. If a word containing a soft hyphen must be split at the end of a line, then this position is preferred.&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|com.sun.star.text.ControlCharacter.HARD_SPACE&lt;br /&gt;
|This control character is used to link two words and prevents this concatenation from being hyphenated. It is printed as a space.&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|com.sun.star.text.ControlCharacter.APPEND_PARAGRAPH&lt;br /&gt;
|This control character appends a new paragraph at the end of the current paragraph.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Although you can insert control codes by inserting the equivalent string (e.g. chr(10) for LINE_BREAK), it is safer to use &amp;lt;tt&amp;gt;insertControlCharacter&amp;lt;/tt&amp;gt; as the screen gets updated properly. &lt;br /&gt;
&lt;br /&gt;
=Changing properties=&lt;br /&gt;
To change the properties of a piece of text, select the text e.g. with a cursor, and then use the &amp;lt;tt&amp;gt;setPropertyValue&amp;lt;/tt&amp;gt; method. &lt;br /&gt;
&lt;br /&gt;
See [[ working with styles]] for an example. &lt;br /&gt;
&lt;br /&gt;
=Paragraphs=&lt;br /&gt;
It is possible to create an enumeration of paragraphs (and text tables) from an object with service [[ TextRange]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; Create enumeration object&lt;br /&gt;
oTextElementEnum = thisComponent.getText.createEnumeration&lt;br /&gt;
&amp;#039;or thisComponent.getCurrentSelection.getByIndex(i).createEnumeration&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; loop over all text elements&lt;br /&gt;
while oTextElementEnum.hasMoreElements()&lt;br /&gt;
        oTextElement = oTextElementEnum.nextElement&lt;br /&gt;
        if oTextElement.supportsService(&amp;quot;com.sun.star.text.TextTable&amp;quot;) then&lt;br /&gt;
                MsgBox &amp;quot;The current block contains a table.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
        if oTextElement.supportsService(&amp;quot;com.sun.star.text.Paragraph&amp;quot;) then&lt;br /&gt;
                MsgBox &amp;quot;The current block contains a paragraph.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
wend&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Text Portions=&lt;br /&gt;
A paragraph consists of text portions. A text portions is a block of text within a paragraph with identical formatting. &lt;br /&gt;
&lt;br /&gt;
The following function counts the number of portions in a paragraph. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnNoPortions(oPara)&lt;br /&gt;
 &lt;br /&gt;
oPortionEnum = oPara.createEnumeration&lt;br /&gt;
i = 0&lt;br /&gt;
while oPortionEnum.hasMoreElements&lt;br /&gt;
        i = i + 1&lt;br /&gt;
        oPortionEnum.nextElement&lt;br /&gt;
wend&lt;br /&gt;
fnNoPortions = i&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
An example of calling this function is: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
thisComponent.getCurrentSelection.getByIndex(i).createEnumeration&lt;br /&gt;
while oTextElementEnum.hasMoreElements()&lt;br /&gt;
        oTextElement = oTextElementEnum.nextElement&lt;br /&gt;
        if oTextElement.supportsService(&amp;quot;com.sun.star.text.TextTable&amp;quot;) then&lt;br /&gt;
                MsgBox &amp;quot;The current block contains a table.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
        if oTextElement.supportsService(&amp;quot;com.sun.star.text.Paragraph&amp;quot;) then&lt;br /&gt;
                MsgBox &amp;quot;The paragraph contains &amp;quot; &amp;amp; fnNoPortions(oTextElement) &amp;amp; &amp;quot;text portions&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
wend&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
For more routines see [[ Working with properties]].&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Working_with_Text_Documents&amp;diff=9367</id>
		<title>Working with Text Documents</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Working_with_Text_Documents&amp;diff=9367"/>
		<updated>2006-05-02T00:48:13Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This section is about working with the Writer component. It builds upon the material covered in [[Extensions_development_basic]] and the generic guides in the [[CookBook]]. &lt;br /&gt;
&lt;br /&gt;
=Cursors=&lt;br /&gt;
To work within a text document typically involves the [[ Current selection]], the [[ View cursor]] or a not visible [[ Text cursor]]. All of them provide access to [[ TextRange]] objects, which provide methods for changing the text. &lt;br /&gt;
&lt;br /&gt;
The differences between them is summarised in the following table: &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
|  &amp;#039;&amp;#039;&amp;#039;Current selection &amp;#039;&amp;#039;&amp;#039;  &lt;br /&gt;
|  &amp;#039;&amp;#039;&amp;#039;View cursor &amp;#039;&amp;#039;&amp;#039;  &lt;br /&gt;
|  &amp;#039;&amp;#039;&amp;#039;Text cursor &amp;#039;&amp;#039;&amp;#039;  &lt;br /&gt;
|-&lt;br /&gt;
|  &amp;#039;&amp;#039;&amp;#039;Typical command &amp;#039;&amp;#039;&amp;#039;  &lt;br /&gt;
|oCurSelection = thisComponent.getCurrentSelection&lt;br /&gt;
|oVC = thisComponent.getCurrentController.getViewCursor&lt;br /&gt;
|oCursor = oVC.getText.createTextCursorByRange(oVC)&lt;br /&gt;
|-&lt;br /&gt;
|  &amp;#039;&amp;#039;&amp;#039;Main service &amp;#039;&amp;#039;&amp;#039;  &lt;br /&gt;
|TextRanges&lt;br /&gt;
|TextViewCursor&lt;br /&gt;
|TextCursor&lt;br /&gt;
|-&lt;br /&gt;
|  &amp;#039;&amp;#039;&amp;#039;Object returned &amp;#039;&amp;#039;&amp;#039;  &lt;br /&gt;
|Array of selected text ranges&lt;br /&gt;
|The insertion point or a single text selection&lt;br /&gt;
|A single text selection&lt;br /&gt;
|-&lt;br /&gt;
|  &amp;#039;&amp;#039;&amp;#039;Number in frame &amp;#039;&amp;#039;&amp;#039;  &lt;br /&gt;
|One array&lt;br /&gt;
|One only&lt;br /&gt;
|As many as required&lt;br /&gt;
|-&lt;br /&gt;
|  &amp;#039;&amp;#039;&amp;#039;Movement &amp;#039;&amp;#039;&amp;#039;  &lt;br /&gt;
|(By view cursor)&lt;br /&gt;
|By Characters, Lines, and Pages&lt;br /&gt;
|By Characters, Words, Sentences, and Paragraphs&lt;br /&gt;
|-&lt;br /&gt;
|  &amp;#039;&amp;#039;&amp;#039;Cookbook page &amp;#039;&amp;#039;&amp;#039;  &lt;br /&gt;
|[[Current selection]]&lt;br /&gt;
|[[ View cursor]]&lt;br /&gt;
|[[ Text cursor]]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
(I have not been able to work out how to select more than one block of text using code other than using the method FindAll. Although it is possible to record a current multiple selection, move the view cursor, and reselect the original multiple selection. See [[View cursor]]. If you know how to do this please edit this page!) &lt;br /&gt;
&lt;br /&gt;
=Text Ranges=&lt;br /&gt;
[[ TextRange]]&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Writer/API/Text_cursor&amp;diff=9366</id>
		<title>Writer/API/Text cursor</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Writer/API/Text_cursor&amp;diff=9366"/>
		<updated>2006-05-02T00:42:37Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A text cursor can only move within the text range of the text object in which it was created. Thus a text cursor that is created for the main document&amp;#039;s text range can not move inside a table. &lt;br /&gt;
&lt;br /&gt;
=Creating a text cursor=&lt;br /&gt;
A common thing to do is to create a text cursor which has the same location as the view cursor, as follows: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oVC = thisComponent.getCurrentController.getViewCursor&lt;br /&gt;
oCursor = oVC.getText.createTextCursorByRange(oVC)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
If you want a cursor for the text in the main document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oCursor = thisComponent.getText.createTextCursor&lt;br /&gt;
&amp;#039;or&lt;br /&gt;
oText = thisComponent.getText&lt;br /&gt;
oCursor = oText.createTextCursorByRange(oText.getStart)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Start and End of a text cursor=&lt;br /&gt;
A cursor has the methods &amp;lt;tt&amp;gt;getStart&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;getEnd&amp;lt;/tt&amp;gt;. Which is the start &amp;quot;end&amp;quot; and which is the end &amp;quot;end&amp;quot; is determined by the direction in which the selection was made. &lt;br /&gt;
&lt;br /&gt;
However, the methods &amp;lt;tt&amp;gt;collapseToStart&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;collpaseToEnd&amp;lt;/tt&amp;gt; are relative to the start and end of the document. &lt;br /&gt;
&lt;br /&gt;
=Moving a cursor=&lt;br /&gt;
A cursor has a number of &amp;lt;tt&amp;gt;gotoXXX&amp;lt;/tt&amp;gt; where XXX is some relative location. In each case there is always a boolean parameter for &amp;quot;extending the selection&amp;quot;. When this parameter is set to &amp;lt;tt&amp;gt;true&amp;lt;/tt&amp;gt; the selection is extended from the current selection to the new location. &lt;br /&gt;
&lt;br /&gt;
There is no method for adding to the selection. While the view cursor can have more than one selection, text cursors only have one selection. &lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;gotoXXX&amp;lt;/tt&amp;gt; methods return true if they were able to execute the movement, false otherwise. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
bExtend = false&lt;br /&gt;
oCursor.goLeft(5, bExtend)   &amp;#039;go left 5 characters&lt;br /&gt;
oCursor.goRight(10, bExtend) &amp;#039;go right 10 characters&lt;br /&gt;
oCursor.gotoStart(bExtend)   &amp;#039;go to the start of the text range&lt;br /&gt;
oCursor.gotoEnd(bExtend)     &amp;#039;go to the end of the text range&lt;br /&gt;
oCursor.gotoRange(oVC, false)&amp;#039;go to the same range as the view cursor (error if oVC not in same text range&lt;br /&gt;
 &lt;br /&gt;
oCursor.gotoNextWord(bExtend)&lt;br /&gt;
oCursor.gotoPreviousWord(bExtend)&lt;br /&gt;
oCursor.gotoEndOfWord(bExtend)&lt;br /&gt;
oCursor.gotoStartOfWord(bExtend)&lt;br /&gt;
 &lt;br /&gt;
oCursor.gotoNextSentence(bExtend)&lt;br /&gt;
oCursor.gotoPreviousSentence(bExtend)&lt;br /&gt;
oCursor.gotoStartOfSentence(bExtend)&lt;br /&gt;
oCursor.gotoEndOfSentence(bExtend)&lt;br /&gt;
 &lt;br /&gt;
oCursor.gotoStartOfParagraph(bExtend)&lt;br /&gt;
oCursor.gotoEndOfParagraph(bExtend)&lt;br /&gt;
oCursor.gotoNextParagraph(bExtend)&lt;br /&gt;
oCursor.gotoPreviousParagraph(bExtend)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Writer/API/View_cursor&amp;diff=9365</id>
		<title>Writer/API/View cursor</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Writer/API/View_cursor&amp;diff=9365"/>
		<updated>2006-05-02T00:40:16Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;View Cursor in a Text document&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
=Accessing the view cursor=&lt;br /&gt;
A view cursor in text document is referenced as follows: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oVC = thisComponent.getCurrentController.getViewCursor&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
It is the only way to move within the page layout. For example to find the start of a line, the top of a page. &lt;br /&gt;
&lt;br /&gt;
=Moving the view cursor=&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
bExtend = false&lt;br /&gt;
oVC.goLeft(5, bExtend)   &amp;#039;go left 5 characters&lt;br /&gt;
oVC.goRight(10, bExtend) &amp;#039;go right 10 characters&lt;br /&gt;
oVC.gotoStart(bExtend)   &amp;#039;go to the start of the text range&lt;br /&gt;
oVC.gotoEnd(bExtend)     &amp;#039;go to the end of the text range&lt;br /&gt;
oVC.gotoRange(oCursor, false) &amp;#039;view cursor can go anywhere&lt;br /&gt;
 &lt;br /&gt;
oVC.goDown(2, bExtend)&lt;br /&gt;
oVC.goLeft(3, bExtend)&lt;br /&gt;
oVC.goUp(1, bExtend) &lt;br /&gt;
oVC.gotoEndOfLine(bExtend)&lt;br /&gt;
oVC.gotoStartOfLine(bExtend)&lt;br /&gt;
 &lt;br /&gt;
oVC.jumpToEndOfPage&lt;br /&gt;
oVC.jumpToFirstPage&lt;br /&gt;
oVC.jumpToLastPage&lt;br /&gt;
oVC.jumpToNextPage&lt;br /&gt;
oVC.jumpToPage(2, false)&lt;br /&gt;
oVC.jumpToPreviousPage&lt;br /&gt;
oVC.jumpToStartOfPage&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Using view cursor to find location on page=&lt;br /&gt;
The following routine returns the current insertion points location on a page in terms of lines and characters. The number of characters is meaningless if the insertion point is in a table. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnPosn(oDoc)&lt;br /&gt;
set mCurSelection = oDoc.currentSelection &amp;#039; Record current selection&lt;br /&gt;
&amp;#039;Locking controller prevents flicker. But under ALL circumstances must be unlocked&lt;br /&gt;
on local error goto finished:&lt;br /&gt;
oDoc.lockControllers&lt;br /&gt;
oVC = oDoc.getCurrentController.getViewCursor&lt;br /&gt;
oVC.collapseToEnd  &amp;#039;Move view Cursor&lt;br /&gt;
oVC.gotoStartofLine(true)&lt;br /&gt;
nX = len(oVC.string)  &amp;#039;How many characters from the start of the line&lt;br /&gt;
nY = 0&lt;br /&gt;
&amp;#039;How many lines from top of page&lt;br /&gt;
nPage = oVC.getPage&lt;br /&gt;
while oVC.goUp(1,false) and oVC.getPage = nPage&lt;br /&gt;
   nY = nY + 1&lt;br /&gt;
wend&lt;br /&gt;
thisComponent.currentController.select(mCurSelection) &amp;#039;Restore current selection&lt;br /&gt;
finished:&lt;br /&gt;
on error goto 0&lt;br /&gt;
oDoc.unlockControllers&lt;br /&gt;
fnPosn = &amp;quot;(&amp;quot; &amp;amp; nx &amp;amp; &amp;quot;, &amp;quot; &amp;amp; nY &amp;amp; &amp;quot;)&amp;quot;&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To call this code: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
msgbox fnPosn(thisComponent)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Updating the status bar with the insertion points current location==&lt;br /&gt;
This code could be called whenever a key is pressed or the mouse clicked so that the status bar is updated with the current insertion point location. As follows: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
global Iannz_TSB_Controller, Iannz_TSB_MouseClickHandler, Iannz_TSB_KeyHandler&lt;br /&gt;
 &lt;br /&gt;
sub subSetupCustomStatusBar&lt;br /&gt;
Iannz_TSB_Controller = thisComponent.currentController&lt;br /&gt;
Iannz_TSB_MouseClickHandler = CreateUnoListener(&amp;quot;MouseClickHandler_&amp;quot;,&amp;quot;com.sun.star.awt.XMouseClickHandler&amp;quot;)&lt;br /&gt;
Iannz_TSB_Controller.addMouseClickHandler(Iannz_TSB_MouseClickHandler)&lt;br /&gt;
Iannz_TSB_KeyHandler = CreateUnoListener(&amp;quot;KeyHandler_&amp;quot;,&amp;quot;com.sun.star.awt.XKeyHandler&amp;quot;)&lt;br /&gt;
Iannz_TSB_Controller.addKeyHandler(Iannz_TSB_KeyHandler)&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
sub subRemoveCustomStatusBar&lt;br /&gt;
if not isNull(Iannz_TSB_Controller) and not isEmpty(Iannz_TSB_Controller) then&lt;br /&gt;
        oStatus = Iannz_TSB_Controller.Frame.createStatusIndicator&lt;br /&gt;
        oStatus.end&lt;br /&gt;
        Iannz_TSB_Controller.removeMouseClickHandler(Iannz_TSB_MouseClickHandler)&lt;br /&gt;
        Iannz_TSB_Controller.removeKeyHandler(Iannz_TSB_KeyHandler)&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
Sub MouseClickHandler_MousePressed(Event As Object)&lt;br /&gt;
Iannz_TSB_Controller.addMouseClickHandler(Iannz_TSB_MouseClickHandler)&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
sub MouseClickHandler_mouseReleased&lt;br /&gt;
subChangeStatusBar&lt;br /&gt;
Iannz_TSB_Controller.addMouseClickHandler(Iannz_TSB_MouseClickHandler)&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
sub MouseClickHandler_disposing&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function KeyHandler_KeyPressed&lt;br /&gt;
KeyHandler_KeyPressed = false&lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function KeyHandler_KeyReleased&lt;br /&gt;
subChangeStatusBar&lt;br /&gt;
KeyHandler_KeyReleased = false&lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
sub KeyHandler_disposing&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
sub subChangeStatusBar&lt;br /&gt;
oDoc = thisComponent&lt;br /&gt;
oVC = Iannz_TSB_Controller.viewCursor&lt;br /&gt;
oStatus = Iannz_TSB_Controller.Frame.createStatusIndicator&lt;br /&gt;
oStatus.end&lt;br /&gt;
if oVC.isCollapsed and isEmpty(oVC.getPropertyValue(&amp;quot;Cell&amp;quot;)) then&lt;br /&gt;
        oStatus.start(fnPosn(thisComponent),100)&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Working_with_Text_Documents&amp;diff=9364</id>
		<title>Working with Text Documents</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Working_with_Text_Documents&amp;diff=9364"/>
		<updated>2006-05-02T00:37:45Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This section is about working with the Writer component. It builds upon the material covered in [[Extensions_development_basic]] and the generic guides in the [[CookBook]]. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Cursors=&lt;br /&gt;
To work within a text document typically involves the [[ Current selection]], the [[ View cursor]] or a not visible [[ Text cursor]]. All of them provide access to [[ TextRange]] objects, which provide methods for changing the text. &lt;br /&gt;
&lt;br /&gt;
The differences between them is summarised in the following table: &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
|  &amp;#039;&amp;#039;&amp;#039;Current selection &amp;#039;&amp;#039;&amp;#039;  &lt;br /&gt;
|  &amp;#039;&amp;#039;&amp;#039;View cursor &amp;#039;&amp;#039;&amp;#039;  &lt;br /&gt;
|  &amp;#039;&amp;#039;&amp;#039;Text cursor &amp;#039;&amp;#039;&amp;#039;  &lt;br /&gt;
|-&lt;br /&gt;
|  &amp;#039;&amp;#039;&amp;#039;Typical command &amp;#039;&amp;#039;&amp;#039;  &lt;br /&gt;
|oCurSelection = thisComponent.getCurrentSelection&lt;br /&gt;
|oVC = thisComponent.getCurrentController.getViewCursor&lt;br /&gt;
|oCursor = oVC.getText.createTextCursorByRange(oVC)&lt;br /&gt;
|-&lt;br /&gt;
|  &amp;#039;&amp;#039;&amp;#039;Main service &amp;#039;&amp;#039;&amp;#039;  &lt;br /&gt;
|[[ TextRanges]]&lt;br /&gt;
|[[ TextViewCursor]]&lt;br /&gt;
|[[ TextCursor]]&lt;br /&gt;
|-&lt;br /&gt;
|  &amp;#039;&amp;#039;&amp;#039;Object returned &amp;#039;&amp;#039;&amp;#039;  &lt;br /&gt;
|Array of selected text ranges&lt;br /&gt;
|The insertion point or a single text selection&lt;br /&gt;
|A single text selection&lt;br /&gt;
|-&lt;br /&gt;
|  &amp;#039;&amp;#039;&amp;#039;Number in frame &amp;#039;&amp;#039;&amp;#039;  &lt;br /&gt;
|One array&lt;br /&gt;
|One only%%!%%&lt;br /&gt;
|As many as required&lt;br /&gt;
|-&lt;br /&gt;
|  &amp;#039;&amp;#039;&amp;#039;Movement &amp;#039;&amp;#039;&amp;#039;  &lt;br /&gt;
|(By view cursor)&lt;br /&gt;
|By Characters, Lines, and Pages&lt;br /&gt;
|By Characters, Words, Sentences, and Paragraphs&lt;br /&gt;
|-&lt;br /&gt;
|  &amp;#039;&amp;#039;&amp;#039;Cookbook page &amp;#039;&amp;#039;&amp;#039;  &lt;br /&gt;
|[[Current selection]]&lt;br /&gt;
|[[View Cursor]]&lt;br /&gt;
|[[Text Cursor]]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(I have not been able to work out how to select more than one block of text using code other than using the method FindAll. Although it is possible to record a current multiple selection, move the view cursor, and reselect the original multiple selection. See [[View Cursor]]. If you know how to do this please edit this page!) &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Text Ranges=&lt;br /&gt;
[[Working with text ranges]]&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Working_with_styles&amp;diff=9363</id>
		<title>Working with styles</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Working_with_styles&amp;diff=9363"/>
		<updated>2006-05-02T00:29:48Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Display Style Names=&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Display style names&amp;#039;&amp;#039;&amp;#039; and &amp;#039;&amp;#039;&amp;#039;style names&amp;#039;&amp;#039;&amp;#039; are sometimes different. Thus to get a list of &amp;#039;display&amp;#039; style names: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnGetDisplayStyleNames(oDoc, sStyleFamily as string)&lt;br /&gt;
dim mApiNames, nStyles as integer, i as integer, oStyles as object&lt;br /&gt;
 &lt;br /&gt;
oStyles = oDoc.getStyleFamilies.getByName(sStyleFamily)&lt;br /&gt;
mApiNames = oStyles.getElementNames&lt;br /&gt;
nStyles = uBound(mApiNames)&lt;br /&gt;
dim mStyleNames(nStyles)&lt;br /&gt;
for i = 0 to nStyles&lt;br /&gt;
        mStyleNames(i) = oStyles.getByIndex(i).getPropertyValue(&amp;quot;DisplayName&amp;quot;)&lt;br /&gt;
next&lt;br /&gt;
subShellSort(mStyleNames())&lt;br /&gt;
fnGetDisplayStyleNames = mStyleNames()&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;subShellSort&amp;lt;/tt&amp;gt; is defined in [[ sorting and searching]]. &lt;br /&gt;
&lt;br /&gt;
An example of calling this function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
mStyleFamilyNames = thisComponent.getStyleFamilies.getElementNames&lt;br /&gt;
for i = 0 to uBound(mStyleFamilyNames)&lt;br /&gt;
        msgbox join(fnGetDisplayStyleNames(thisComponent, mStyleFamilyNames(i)), chr(13)), 0, mStyleFamilyNames(i)&lt;br /&gt;
next&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Number formats=&lt;br /&gt;
Number formats have an Id number. Here is a function for getting that number: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnGetNumberFormatId(oDoc, sNumberFormat)&lt;br /&gt;
sCharLocale = oDoc.getPropertyValue(&amp;quot;CharLocale&amp;quot;)&lt;br /&gt;
nFormatId = oDoc.getNumberFormats.queryKey(sNumberFormat, sCharLocale, false)&lt;br /&gt;
if nFormatId = -1 then  &amp;#039;Not yet defined&lt;br /&gt;
        nFormatId = oDoc.getNumberFormats.addNew(sNumberFormat, sCharLocale)&lt;br /&gt;
end if&lt;br /&gt;
fnGetNumberFormatId = nFormatId&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
An example for directly applying a number format to a range of cells in a spreadsheet: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oCells = thisComponent.getSheets.getByIndex(0).getCellRangeByName(&amp;quot;B2:B10&amp;quot;)&lt;br /&gt;
nFourDP = fnGetNumberFormatId(thisComponent, &amp;quot;0.0000&amp;quot;)&lt;br /&gt;
oCells.setPropertyValue(&amp;quot;NumberFormat&amp;quot;, nFourDp)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Get Style=&lt;br /&gt;
The following function is for returning a style of a particular name, if the name doesn&amp;#039;t already exist a style is created with that name. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnGetStyle(oDoc, sStyleFamily, sInstance, sStyleName)&lt;br /&gt;
oStyles = thisComponent.getStyleFamilies.getByName(sStyleFamily)&lt;br /&gt;
if not oStyles.hasByName(sStyleName) then&lt;br /&gt;
        oStyle = thisComponent.createInstance(sInstance)&lt;br /&gt;
        oStyles.insertByName(sStyleName, oStyle)&lt;br /&gt;
else&lt;br /&gt;
        oStyle = oStyles.getByName(sStyleName)&lt;br /&gt;
end if&lt;br /&gt;
fnGetStyle = oStyle&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
(It would be good if the sInstance parameter could be removed but I haven&amp;#039;t worked out how to do that. If you work it out please edit this page!) &lt;br /&gt;
&lt;br /&gt;
An example of calling the above function, it creates a cell style called FourDP if it doesn&amp;#039;t already exist, sets its number format, and applys the cell format to a range of cells: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sStyle = &amp;quot;FourDP&amp;quot;&lt;br /&gt;
oStyle = fnGetStyle(thisComponent, &amp;quot;CellStyles&amp;quot;, &amp;quot;com.sun.star.style.CellStyle&amp;quot;, sStyle)&lt;br /&gt;
oStyle.setPropertyValue(&amp;quot;NumberFormat&amp;quot;, fnGetNumberFormatId(thisComponent, &amp;quot;0.0000&amp;quot;)&lt;br /&gt;
oCells = thisComponent.getSheets.getByIndex(0).getCellRangeByName(&amp;quot;B2:B10&amp;quot;)&lt;br /&gt;
oCells.setPropertyValue(&amp;quot;CellStyle&amp;quot;, sStyle)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Find Style=&lt;br /&gt;
To find an existing style that has the properties that you want: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnFindStyle(oDoc, sStyleFamily, mProperties)&lt;br /&gt;
oStyleFamilies = oDoc.StyleFamilies&lt;br /&gt;
oStyles = oStyleFamilies.getByName(sStyleFamily)&lt;br /&gt;
nProperties = ubound(mProperties)&lt;br /&gt;
For i = 0 To oStyles.Count - 1&lt;br /&gt;
   oStyle = oStyles(i)&lt;br /&gt;
   bFound = true&lt;br /&gt;
   for j = 0 to nProperties&lt;br /&gt;
      if oStyle.getPropertyValue(mProperties(j).name) &amp;lt;&amp;gt; mProperties(j).value then&lt;br /&gt;
         bFound = false&lt;br /&gt;
         exit for&lt;br /&gt;
      end if&lt;br /&gt;
   next&lt;br /&gt;
   if bFound then&lt;br /&gt;
      fnFindStyle = oStyle&lt;br /&gt;
      exit function&lt;br /&gt;
   end if&lt;br /&gt;
next&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
An example of calling this function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
dim mProperties()&lt;br /&gt;
subAddProperty(mProperties(), &amp;quot;NumberFormat&amp;quot;, fnGetNumberFormatId(thisComponent, &amp;quot;0.0000&amp;quot;))&lt;br /&gt;
oStyle = fnFindStyle(thisComponent, &amp;quot;CellStyles&amp;quot;, mProperties())&lt;br /&gt;
if isNull(oStyle) then&lt;br /&gt;
   sStyle = &amp;quot;FourDP&amp;quot;&lt;br /&gt;
   oStyle = fnGetStyle(thisComponent, &amp;quot;CellStyles&amp;quot;, &amp;quot;com.sun.star.style.CellStyle&amp;quot;, sStyle)&lt;br /&gt;
   oStyle.setPropertyValues(mProperties())&lt;br /&gt;
else&lt;br /&gt;
   sStyle = oStyle.getName&lt;br /&gt;
end if&lt;br /&gt;
oCells = thisComponent.getSheets.getByIndex(0).getCellRangeByName(&amp;quot;B2:B10&amp;quot;)&lt;br /&gt;
oCells.setPropertyValue(&amp;quot;CellStyle&amp;quot;, sStyle)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This example calls &amp;lt;tt&amp;gt;subAddProperty&amp;lt;/tt&amp;gt; which is defined in [[Working_with_properties#subAddProperty]].&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Sorting_and_searching&amp;diff=9362</id>
		<title>Sorting and searching</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Sorting_and_searching&amp;diff=9362"/>
		<updated>2006-05-02T00:25:57Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Neither OpenOffice.org Basic nor the API provide methods or functions for sorting arrays or searching within arrays.&lt;br /&gt;
&lt;br /&gt;
It is quite common to sort almost sorted arrays, for example the list of style names belonging to a style family. Thus, I have found the shell sort to be the fastest for most uses in OpenOffice.org: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub subShellSort(mArray)&lt;br /&gt;
 &lt;br /&gt;
dim n as integer, h as integer, i as integer, j as integer, t as string, Ub as integer, LB as integer&lt;br /&gt;
Lb = lBound(mArray)&lt;br /&gt;
Ub = uBound(mArray)&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; compute largest increment&lt;br /&gt;
n = Ub - Lb + 1&lt;br /&gt;
h = 1&lt;br /&gt;
if n &amp;gt; 14 then&lt;br /&gt;
        do while h &amp;lt; n&lt;br /&gt;
                h = 3 * h + 1&lt;br /&gt;
        loop&lt;br /&gt;
        h = h \ 3&lt;br /&gt;
        h = h \ 3&lt;br /&gt;
end if&lt;br /&gt;
do while h &amp;gt; 0&lt;br /&gt;
&amp;#039; sort by insertion in increments of h&lt;br /&gt;
        for i = Lb + h to Ub&lt;br /&gt;
                t = mArray(i)&lt;br /&gt;
                for j = i - h to Lb step -h&lt;br /&gt;
                        if strComp(mArray(j), t, 0) &amp;lt; 1 then exit for&lt;br /&gt;
                        mArray(j + h) = mArray(j)&lt;br /&gt;
                next j&lt;br /&gt;
                mArray(j + h) = t&lt;br /&gt;
        next i&lt;br /&gt;
        h = h \ 3&lt;br /&gt;
loop&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Based on a routine available from [[http://www.oopweb.com/Algorithms/Documents/Sman/Volume/s_vss.txt here]]. &lt;br /&gt;
&lt;br /&gt;
Searching in a sorted list is compartively efficient with a binary search: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnBinarySearch(a, v)&lt;br /&gt;
nLeft = 0&lt;br /&gt;
nRight = uBound(a)&lt;br /&gt;
nLen = len(v)&lt;br /&gt;
while nLeft &amp;lt;= nRight&lt;br /&gt;
        nMid = int((nLeft + nRight)/2)&lt;br /&gt;
        if left(a(nMid), nLen) = v then&lt;br /&gt;
                fnBinarySearch = nMid&lt;br /&gt;
                exit function&lt;br /&gt;
        elseif v &amp;lt; a(nMid) then&lt;br /&gt;
                nRight = nMid - 1&lt;br /&gt;
        else&lt;br /&gt;
                nLeft = nMid + 1&lt;br /&gt;
        end if&lt;br /&gt;
wend&lt;br /&gt;
fnBinarySearch = -1&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Working_with_properties&amp;diff=9361</id>
		<title>Working with properties</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Working_with_properties&amp;diff=9361"/>
		<updated>2006-05-02T00:23:05Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The following routines all deal with properties. They are revised routines from my RevealCodes macro, and the main routine which demonstrates calling some of the other routines displays the changes in &amp;quot;codes&amp;quot; for the current paragraph.&lt;br /&gt;
&lt;br /&gt;
=fnNotIn=&lt;br /&gt;
The following routine compares two arrays or property beans, and returns an array of property beans for those items which are in array mProp1 but not in mProp2, or where the value is different. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnNotIn(mProp1, mProp2)&lt;br /&gt;
&amp;#039;Returns an array of the properties in mProp1 not found in mProp2&lt;br /&gt;
dim mNotIn()&lt;br /&gt;
n1 = uBound(mProp1)&lt;br /&gt;
n2 = uBound(mProp2)&lt;br /&gt;
if n2 &amp;lt; 0 then&lt;br /&gt;
        fnNotIn = mProp1&lt;br /&gt;
else&lt;br /&gt;
        for i = 0 to n1&lt;br /&gt;
                sName1 = mProp1(i).name&lt;br /&gt;
                bNotFound = true&lt;br /&gt;
                for j = 0 to n2&lt;br /&gt;
                        sName2 = mProp2(j).name&lt;br /&gt;
                        if sName1 = sName2 then&lt;br /&gt;
                                bNotFound = not fnEqualValues(mProp1(i).value, mProp2(j).value)&lt;br /&gt;
                                exit for&lt;br /&gt;
                        elseif sName2 &amp;gt; sName1 then&lt;br /&gt;
                                exit for&lt;br /&gt;
                        end if&lt;br /&gt;
                next&lt;br /&gt;
                if bNotFound then subAddThisProperty(mNotIn(), mProp1(i))&lt;br /&gt;
        next&lt;br /&gt;
        fnNotIn = mNotIn()&lt;br /&gt;
end if&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=fnEqualValues=&lt;br /&gt;
This routine is not strictly dealing with properties but is called by fnNotIn, so is included here. The function is recursive so will only work in OpenOffice.org 1.1.1 or greater. Compares two values of the same type and returns whether they are equal or not. Currently it doesn&amp;#039;t work for structs or objects (if you know how to do this please edit this page!) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnEqualValues(vValue1, vValue2) as boolean&lt;br /&gt;
&amp;#039;Returns true if the values are equal&lt;br /&gt;
 &lt;br /&gt;
if isArray(vValue) then&lt;br /&gt;
        nUpperBound1 = uBound(vValue1)&lt;br /&gt;
        nUpperBound2 = uBound(vValue2)&lt;br /&gt;
        if nUpperBound1 &amp;lt;&amp;gt; nUpperBound2 then&lt;br /&gt;
                fnEqualValues = false&lt;br /&gt;
        elseif nUpperBound1 = -1 then&lt;br /&gt;
                fnEqualValues = true&lt;br /&gt;
        else&lt;br /&gt;
                for i = 0 to nUpperBound1&lt;br /&gt;
                        if not fnEqualValues(vValue1, vValue2) then&lt;br /&gt;
                                fnEqualValues = false&lt;br /&gt;
                                exit for&lt;br /&gt;
                        end if&lt;br /&gt;
                next&lt;br /&gt;
        end if&lt;br /&gt;
elseif isUNOstruct(vValue) then&lt;br /&gt;
        fnEqualValues = true &amp;#039;Assume true as I don&amp;#039;t know how to compare them&lt;br /&gt;
else&lt;br /&gt;
        select case varType(vValue)&lt;br /&gt;
        case 2-5,7, 8, 11 &amp;#039;numbers, date, string boolean&lt;br /&gt;
                fnEqualValues = vValue1 = vValue2&lt;br /&gt;
        case 9  &amp;#039;object ???&lt;br /&gt;
                        fnEqualValues = true &amp;#039;Assume true as I don&amp;#039;t know how to compare them&lt;br /&gt;
        case else&lt;br /&gt;
                fnEqualValues = true&lt;br /&gt;
        end select&lt;br /&gt;
end if&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=subAddThisProperty=&lt;br /&gt;
This routine adds a property bean to the end of a one dimensional array. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub subAddThisProperty(mProperties, mProperty)&lt;br /&gt;
nNext = uBound(mProperties) + 1&lt;br /&gt;
redim preserve mProperties(nNext)&lt;br /&gt;
set mProperties(nNext) = mProperty&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=fnDirectProperties=&lt;br /&gt;
Returns an array of property beans of directly applied properties to a text range (should work for other types of objects but has not been tested). &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnDirectProperties(oTextRange)&lt;br /&gt;
&amp;#039;Returns an array of property beans of directly applied properties&lt;br /&gt;
oProperties = oTextRange.getPropertySetInfo.getProperties&lt;br /&gt;
nProperties = uBound(oProperties)&lt;br /&gt;
dim mDirectProperties()&lt;br /&gt;
for i = 0 to nProperties&lt;br /&gt;
        sName = oProperties(i).name&lt;br /&gt;
        if oTextRange.getPropertyState(sName) &amp;lt;&amp;gt; com.sun.star.beans.PropertyState.DEFAULT_VALUE and _&lt;br /&gt;
         ((oProperties(i).attributes and com.sun.star.beans.PropertyAttribute.READONLY) = 0) then &lt;br /&gt;
                nTypeClass = oProperties(i).type.typeClass&lt;br /&gt;
                subAddProperty( mDirectProperties(),sName, oTextRange.getPropertyValue(sName))&lt;br /&gt;
        end if&lt;br /&gt;
next&lt;br /&gt;
fnDirectProperties = mDirectProperties()&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=fnPropertyValues=&lt;br /&gt;
Returns an array of strings for the property names and their values. You could think of this as being a form of introspection. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnPropertyValues(mProperties)&lt;br /&gt;
&amp;#039;returns an array of strings for the property names and their values&lt;br /&gt;
nProperties = Ubound(mProperties)&lt;br /&gt;
if nProperties &amp;lt; 0 then&lt;br /&gt;
        fnPropertyValues = array(&amp;quot;&amp;quot;)&lt;br /&gt;
        exit function&lt;br /&gt;
end if&lt;br /&gt;
dim mPropertyValues(nProperties)&lt;br /&gt;
for i = 0 to nProperties&lt;br /&gt;
        mPropertyValues(i) = fnPropertyValue(mProperties(i))&lt;br /&gt;
next&lt;br /&gt;
fnPropertyValues = mPropertyValues()&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=fnPropertyValue=&lt;br /&gt;
Returns the concatentaion of a property name and its value as a string &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnPropertyValue(aProperty) as string&lt;br /&gt;
&amp;#039;Returns the concatentaion of a property name and its value as a string&lt;br /&gt;
if isNull(aProperty) or isEmpty(aProperty) then&lt;br /&gt;
        fnPropertyValue = &amp;quot;&amp;quot;&lt;br /&gt;
        msgbox &amp;quot;Oops!&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
        sName = aProperty.name&lt;br /&gt;
        vValue = aProperty.Value&lt;br /&gt;
        fnPropertyValue = sName &amp;amp; &amp;quot;: &amp;quot; &amp;amp; fnConvString(vValue)&lt;br /&gt;
end if&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=fnConvString=&lt;br /&gt;
Converts a variables value to a string. Currently if the variable is a struct or object it simply returns &amp;quot;Struct&amp;quot; or &amp;quot;Object&amp;quot;. (If you know a better way please edit this page!) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnConvString(vValue) as string&lt;br /&gt;
&amp;#039;Converts a variant to a string&lt;br /&gt;
if isArray(vValue) then&lt;br /&gt;
        nUpperBound = uBound(vValue)&lt;br /&gt;
        if nUpperBound = 0 then&lt;br /&gt;
                fnConvString = &amp;quot;&amp;quot;&lt;br /&gt;
        else&lt;br /&gt;
                s = &amp;quot;{&amp;quot;&lt;br /&gt;
                for i = 0 to nUpperBound&lt;br /&gt;
                        s = s &amp;amp; fnConvString(vValue(i)) &amp;amp; &amp;quot;,&amp;quot;&lt;br /&gt;
                next&lt;br /&gt;
                nLen = len(s)&lt;br /&gt;
                if nLen &amp;gt; 1 then&lt;br /&gt;
                        fnConvString = left(s, len(s) - 1) &amp;amp; &amp;quot;}&amp;quot;&lt;br /&gt;
                end if&lt;br /&gt;
        end if&lt;br /&gt;
elseif isUNOstruct(vValue) then&lt;br /&gt;
        fnConvString = &amp;quot;Struct&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
        select case varType(vValue)&lt;br /&gt;
        case 0, 2 to 5,7 &amp;#039;empty, numbers, date&lt;br /&gt;
                fnConvString = cstr(vValue)&lt;br /&gt;
        case 8  &amp;#039;string&lt;br /&gt;
                fnConvString = vValue&lt;br /&gt;
        case 9  &amp;#039;object ???&lt;br /&gt;
                fnConvString = &amp;quot;Object&amp;quot;&lt;br /&gt;
        case 11 &amp;#039;boolean&lt;br /&gt;
                if vValue then&lt;br /&gt;
                        fnConvString = &amp;quot;True&amp;quot;&lt;br /&gt;
                else&lt;br /&gt;
                        fnConvString = &amp;quot;False&amp;quot;&lt;br /&gt;
                end if&lt;br /&gt;
        case else&lt;br /&gt;
                fnConvString = &amp;quot;&amp;quot;&amp;#039;vValue&lt;br /&gt;
                msgbox varType(vValue)&lt;br /&gt;
        end select&lt;br /&gt;
end if&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=subAddProperty=&lt;br /&gt;
This routine calls fnNewProperty to create new property bean, assign a name and optionally a value, and adds the new property bean to a one dimensional array. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub subAddProperty(mProperties, sName, optional vValue)&lt;br /&gt;
nNext = uBound(mProperties) + 1&lt;br /&gt;
redim preserve mProperties(nNext)&lt;br /&gt;
if isMissing(vValue) then&lt;br /&gt;
        mProperties(nNext) = fnNewProperty(sName)&lt;br /&gt;
else&lt;br /&gt;
        mProperties(nNext) = fnNewProperty(sName, vValue)&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=fnNewProperty=&lt;br /&gt;
Create new property bean, assign a name and optionally a value, returns the new property bean. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnNewProperty(sName, optional vValue)&lt;br /&gt;
aProperty = createUnoStruct(&amp;quot;com.sun.star.beans.PropertyValue&amp;quot;)&lt;br /&gt;
aProperty.Name = sName&lt;br /&gt;
if not isMissing(vValue) then&lt;br /&gt;
        aProperty.Value = vValue&lt;br /&gt;
end if&lt;br /&gt;
fnNewProperty = aProperty&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Example - Displaying &amp;#039;codes&amp;#039; of a paragraph=&lt;br /&gt;
This example demonstrates calling &amp;lt;tt&amp;gt;fnDirectProperties&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;fnNotIn&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;fnPropertyValues&amp;lt;/tt&amp;gt; defined above. It shows how the above codes could be used in a &amp;quot;reveal codes&amp;quot; type macro. The [[ join]] statement is just a quick and dirty way of creating a string out of an array of strings for displaying in the messagebox. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
oParagraph = fnGetCurrentParagraph&lt;br /&gt;
mParaProperties = fnDirectProperties(oParagraph)&lt;br /&gt;
msgbox join(fnPropertyValues(mParaProperties), chr(10)), 0 , &amp;quot;Paragraph properties&amp;quot;&lt;br /&gt;
oPortionEnum = oParagraph.createEnumeration&lt;br /&gt;
i = 0&lt;br /&gt;
while oPortionEnum.hasMoreElements&lt;br /&gt;
        i = i + 1&lt;br /&gt;
        oPortion = oPortionEnum.nextElement&lt;br /&gt;
        mCurProperties = fnDirectProperties(oPortion)&lt;br /&gt;
        if i &amp;gt; 1 then&lt;br /&gt;
                mCloseProperties = fnNotIn(mPrevProperties, mCurProperties)&lt;br /&gt;
                msgbox join(fnPropertyValues(mCloseProperties), chr(10)), 0 , &amp;quot;Portion &amp;quot; &amp;amp; i &amp;amp; &amp;quot; close properties&amp;quot;&lt;br /&gt;
                mOpenProperties = fnNotIn(mCurProperties, mPrevProperties)&lt;br /&gt;
        else&lt;br /&gt;
                mOpenProperties = mCurProperties&lt;br /&gt;
        end if&lt;br /&gt;
        msgbox join(fnPropertyValues(mOpenProperties), chr(10)), 0 , &amp;quot;Portion &amp;quot; &amp;amp; i &amp;amp; &amp;quot; open properties&amp;quot;&lt;br /&gt;
        set mPrevProperties = mCurProperties&lt;br /&gt;
wend&lt;br /&gt;
msgbox join(fnPropertyValues(mPrevProperties), chr(10)), 0 , &amp;quot;Portion &amp;quot; &amp;amp; i &amp;amp; &amp;quot; close properties&amp;quot;&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function fnGetCurrentParagraph&lt;br /&gt;
&amp;#039;Returns the whole paragraph that the insertion point is in&lt;br /&gt;
oVC = thisComponent.getCurrentController.getViewCursor&lt;br /&gt;
oCursor = oVC.text.createTextCursorByRange(oVC)&lt;br /&gt;
oCursor.gotoStartOfParagraph(false)&lt;br /&gt;
oCursor.gotoEndOfParagraph(true)&lt;br /&gt;
fnGetCurrentParagraph = oCursor.createEnumeration.nextElement&lt;br /&gt;
end function&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Closing_a_document&amp;diff=9360</id>
		<title>Closing a document</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Closing_a_document&amp;diff=9360"/>
		<updated>2006-05-02T00:18:59Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
thisComponent.close(true)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Please note that the parameter being passed is to do with what should happen if another process has vetoed closing the document or not and not whether the document is to be saved. &lt;br /&gt;
&lt;br /&gt;
So to be sure that a document gets saved before closing use something like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub subClose(oDoc)&lt;br /&gt;
if fnSave(oDoc) then&lt;br /&gt;
        oDoc.close(true)&lt;br /&gt;
        fnClose = true&lt;br /&gt;
else&lt;br /&gt;
        if msgbox(&amp;quot;Unable to save the file before closing.&amp;quot; &amp;amp; chr(13) &amp;amp; _&lt;br /&gt;
         &amp;quot;Close any way?&amp;quot;, 4 + 32, &amp;quot;File not saved warning&amp;quot;) = 6 then&lt;br /&gt;
           oDoc.close(true)&lt;br /&gt;
        end if&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
fnSave is defined [[saving a document]]. &lt;br /&gt;
&lt;br /&gt;
Example of calling &amp;lt;tt&amp;gt;subclose&amp;lt;/tt&amp;gt;: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
subClose(thisComponent)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Warning:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|Do not use &amp;lt;tt&amp;gt;thisComponent.dispose&amp;lt;/tt&amp;gt; it could crash OpenOffice.org.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Printing_a_document&amp;diff=9359</id>
		<title>Printing a document</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Printing_a_document&amp;diff=9359"/>
		<updated>2006-05-02T00:15:36Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;To print the current document without passing any arguments: &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
thisComponent.print(array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
A more generic print routine: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub subPrint(oDoc, optional ncopies, optional bCollate, optional sPages, optional sFileName)&lt;br /&gt;
dim mPrintOptions()&lt;br /&gt;
 &lt;br /&gt;
if not isMissing(nCopies) then&lt;br /&gt;
        subAddproperty(mPrintOptions(), &amp;quot;CopyCount&amp;quot;, nCopies)&lt;br /&gt;
end if&lt;br /&gt;
if not isMissing(bCollate) then&lt;br /&gt;
        subAddproperty(mPrintOptions(), &amp;quot;Collate&amp;quot;, bCollate)&lt;br /&gt;
end if&lt;br /&gt;
if not isMissing(sPages) then&lt;br /&gt;
        subAddproperty(mPrintOptions(), &amp;quot;Pages&amp;quot;, sPages)&lt;br /&gt;
end if&lt;br /&gt;
if not isMissing(sFilename) then&lt;br /&gt;
        subAddproperty(mPrintOptions(), &amp;quot;FileName&amp;quot;, sFileName)&lt;br /&gt;
end if&lt;br /&gt;
oDoc.print(mPrintOptions())&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This function calls subAddProperty which is defined in [[working with properties]]. &lt;br /&gt;
&lt;br /&gt;
Example of calling this function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
subprint(ThisComponent, 1, ,&amp;quot;1&amp;quot;, &amp;quot;PrintExample.txt&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Saving_a_document&amp;diff=9358</id>
		<title>Saving a document</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Saving_a_document&amp;diff=9358"/>
		<updated>2006-05-02T00:12:30Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;To save an existing document: &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
thisComponent.store()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
But, this maybe a bit too simplistic. So a more generic approach might be: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnSave(oDoc)&lt;br /&gt;
if oDoc.hasLocation AND Not oDoc.isReadOnly Then&lt;br /&gt;
   fnSave = true&lt;br /&gt;
   on local error goto notSaved&lt;br /&gt;
   oDoc.store()&lt;br /&gt;
   on error goto 0&lt;br /&gt;
else&lt;br /&gt;
   fnSave = fnDispatch(&amp;quot;SaveAs&amp;quot;)&lt;br /&gt;
end If&lt;br /&gt;
exit function&lt;br /&gt;
 &lt;br /&gt;
notSaved:&lt;br /&gt;
fnSave = false&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
fnDispatch is defined in [[ The OpenOffice.org recorder and UNO dispatch calls]]. &lt;br /&gt;
&lt;br /&gt;
To &amp;quot;save as&amp;quot;: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub subSaveAs(oDoc, sFile, optional sType)&lt;br /&gt;
sURL = convertToURL(sFile)&lt;br /&gt;
if isMissing(sType) then&lt;br /&gt;
   oDoc.storeAsURL(sURL, array())&lt;br /&gt;
else&lt;br /&gt;
  dim mFileType(0)&lt;br /&gt;
  mFileType(0) = createUnoStruct(&amp;quot;com.sun.star.beans.PropertyValue&amp;quot;)&lt;br /&gt;
  mFileType(0).Name = &amp;quot;FilterName&amp;quot;&lt;br /&gt;
  mFileType(0).Value = sType&lt;br /&gt;
  oDoc.storeAsURL(sURL, mFileType())&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To &amp;quot;export as&amp;quot; (leave the URL of the current document alone but save a copy of the file in the specified format): &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub subExportAs(oDoc, sFile, optional sType)&lt;br /&gt;
sURL = convertToURL(sFile)&lt;br /&gt;
if isMissing(sType) then&lt;br /&gt;
   oDoc.storeToURL(sURL, array())&lt;br /&gt;
else&lt;br /&gt;
  dim mFileType(0)&lt;br /&gt;
  mFileType(0) = createUnoStruct(&amp;quot;com.sun.star.beans.PropertyValue&amp;quot;)&lt;br /&gt;
  mFileType(0).Name = &amp;quot;FilterName&amp;quot;&lt;br /&gt;
  mFileType(0).Value = sType&lt;br /&gt;
  oDoc.storeToURL(sURL, mFileType())&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Examples of calling these routines: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
subSaveAs(thisComponent, &amp;quot;C:\tmp\NewName.sxw&amp;quot;) &amp;#039;Windows example&lt;br /&gt;
subExportAs(thisComponent, &amp;quot;/home/ian/Example.txt&amp;quot;, &amp;quot;Text&amp;quot;) &amp;#039;Linux example&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=File Types=&lt;br /&gt;
The following routine, written by Danny Brewer (copied from [[http://www.oooforum.org/forum/viewtopic.phtml?t=3549 here]]) creates a new document and enters the current filters. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Sub Main&lt;br /&gt;
oFF = createUnoService( &amp;quot;com.sun.star.document.FilterFactory&amp;quot; )&lt;br /&gt;
oFilterNames = oFF.getElementNames()&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; Create a Writer doc and save the filter names to it.&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL( &amp;quot;private:factory/swriter&amp;quot;, &amp;quot;_blank&amp;quot;, 0, Array() )&lt;br /&gt;
oText = oDoc.getText()&lt;br /&gt;
oCursor = oText.createTextCursor()&lt;br /&gt;
oCursor.gotoEnd( False )&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; Print the filter names into a Writer document.&lt;br /&gt;
For i = LBound( oFilterNames ) To UBound( oFilterNames )&lt;br /&gt;
   oText.insertString( oCursor, oFilterNames(i), False )&lt;br /&gt;
      oText.insertControlCharacter( oCursor, com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK, False )&lt;br /&gt;
Next&lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Saving_a_document&amp;diff=9357</id>
		<title>Saving a document</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Saving_a_document&amp;diff=9357"/>
		<updated>2006-05-02T00:11:01Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;To save an existing document: &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
thisComponent.store()&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
But, this maybe a bit too simplistic. So a more generic approach might be: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnSave(oDoc)&lt;br /&gt;
if oDoc.hasLocation AND Not oDoc.isReadOnly Then&lt;br /&gt;
   fnSave = true&lt;br /&gt;
   on local error goto notSaved&lt;br /&gt;
   oDoc.store()&lt;br /&gt;
   on error goto 0&lt;br /&gt;
else&lt;br /&gt;
   fnSave = fnDispatch(&amp;quot;SaveAs&amp;quot;)&lt;br /&gt;
end If&lt;br /&gt;
exit function&lt;br /&gt;
 &lt;br /&gt;
notSaved:&lt;br /&gt;
fnSave = false&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
fnDispatch is defined in [[ The OpenOffice.org recorder and UNO dispatch calls]]. &lt;br /&gt;
&lt;br /&gt;
To &amp;quot;save as&amp;quot;: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub subSaveAs(oDoc, sFile, optional sType)&lt;br /&gt;
sURL = convertToURL(sFile)&lt;br /&gt;
if isMissing(sType) then&lt;br /&gt;
   oDoc.storeAsURL(sURL, array())&lt;br /&gt;
else&lt;br /&gt;
  dim mFileType(0)&lt;br /&gt;
  mFileType(0) = createUnoStruct(&amp;quot;com.sun.star.beans.PropertyValue&amp;quot;)&lt;br /&gt;
  mFileType(0).Name = &amp;quot;FilterName&amp;quot;&lt;br /&gt;
  mFileType(0).Value = sType&lt;br /&gt;
  oDoc.storeAsURL(sURL, mFileType())&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To &amp;quot;export as&amp;quot; (leave the URL of the current document alone but save a copy of the file in the specified format): &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub subExportAs(oDoc, sFile, optional sType)&lt;br /&gt;
sURL = convertToURL(sFile)&lt;br /&gt;
if isMissing(sType) then&lt;br /&gt;
   oDoc.storeToURL(sURL, array())&lt;br /&gt;
else&lt;br /&gt;
  dim mFileType(0)&lt;br /&gt;
  mFileType(0) = createUnoStruct(&amp;quot;com.sun.star.beans.PropertyValue&amp;quot;)&lt;br /&gt;
  mFileType(0).Name = &amp;quot;FilterName&amp;quot;&lt;br /&gt;
  mFileType(0).Value = sType&lt;br /&gt;
  oDoc.storeToURL(sURL, mFileType())&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Examples of calling these routines: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
subSaveAs(thisComponent, &amp;quot;C:\tmp\NewName.sxw&amp;quot;) &amp;#039;Windows example&lt;br /&gt;
subExportAs(thisComponent, &amp;quot;/home/ian/Example.txt&amp;quot;, &amp;quot;Text&amp;quot;) &amp;#039;Linux example&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
For more information on &amp;lt;tt&amp;gt;saveAsURL&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;saveToURL&amp;lt;/tt&amp;gt; see [[ XStorable]] and for the parameters that can be passed to them see [[ MediaDescriptor]]. Use the above examples as templates for how to use these parameters in Basic. &lt;br /&gt;
&lt;br /&gt;
Read on for the complete list of filters that can be passed to these functions. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=File Types=&lt;br /&gt;
The following routine, written by Danny Brewer (copied from [[http://www.oooforum.org/forum/viewtopic.phtml?t=3549 here]]) creates a new document and enters the current filters. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Sub Main&lt;br /&gt;
oFF = createUnoService( &amp;quot;com.sun.star.document.FilterFactory&amp;quot; )&lt;br /&gt;
oFilterNames = oFF.getElementNames()&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; Create a Writer doc and save the filter names to it.&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL( &amp;quot;private:factory/swriter&amp;quot;, &amp;quot;_blank&amp;quot;, 0, Array() )&lt;br /&gt;
oText = oDoc.getText()&lt;br /&gt;
oCursor = oText.createTextCursor()&lt;br /&gt;
oCursor.gotoEnd( False )&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; Print the filter names into a Writer document.&lt;br /&gt;
For i = LBound( oFilterNames ) To UBound( oFilterNames )&lt;br /&gt;
   oText.insertString( oCursor, oFilterNames(i), False )&lt;br /&gt;
      oText.insertControlCharacter( oCursor, com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK, False )&lt;br /&gt;
Next&lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Opening_a_document&amp;diff=9356</id>
		<title>Opening a document</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Opening_a_document&amp;diff=9356"/>
		<updated>2006-05-02T00:03:29Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;The following function opens a file into a new window. &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnOpenDoc(sFile)&lt;br /&gt;
sURL = ConvertToURL(sFile)&lt;br /&gt;
fnOpenDoc = StarDesktop.loadComponentFromURL(sURL, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Examples of calling the function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = fnOpenDoc(&amp;quot;C:\Documents and Settings\danny\Desktop\MyCalc.sxc&amp;quot;) &amp;#039; Windows&lt;br /&gt;
oDoc = fnOpenDoc(&amp;quot;/home/danny/Desktop/MyCalc.sxc&amp;quot;) &amp;#039; Linux&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
A more complete function for opening a file: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnOpenDoc(sFile, optional bAsTemplate, optional sPassword, optional bReadOnly, _&lt;br /&gt;
  optional nMacroExecutionMode, optional nUpdateDocMode, optional sJumpMark, _&lt;br /&gt;
  optional nViewId, optional bHidden, optional bStartPresentation,_&lt;br /&gt;
  optional sFilterName, optional sFilterOptions, optional vFilterData, optional bRepairPackage)&lt;br /&gt;
 &lt;br /&gt;
dim mFileProperties()&lt;br /&gt;
 &lt;br /&gt;
if not isMissing(bAsTemplate) then&lt;br /&gt;
        subAddproperty(mFileProperties(), &amp;quot;AsTemplate&amp;quot;, bAsTemplate)&lt;br /&gt;
end if&lt;br /&gt;
if not isMissing(sPassword) then&lt;br /&gt;
        subAddproperty(mFileProperties(), &amp;quot;Password&amp;quot;, sPassword)&lt;br /&gt;
end if&lt;br /&gt;
if not isMissing(bReadOnly) then&lt;br /&gt;
        subAddproperty(mFileProperties(), &amp;quot;ReadOnly&amp;quot;, bReadOnly)&lt;br /&gt;
end if&lt;br /&gt;
if not isMissing(nMacroExecutionMode) then&lt;br /&gt;
        subAddproperty(mFileProperties(), &amp;quot;MacroExecutionMode&amp;quot;, nMacroExecutionMode)&lt;br /&gt;
end if&lt;br /&gt;
if not isMissing(nUpdateDocMode) then&lt;br /&gt;
        subAddproperty(mFileProperties(), &amp;quot;UpdateDocMode&amp;quot;, nUpdateDocMode)&lt;br /&gt;
end if&lt;br /&gt;
if not isMissing(sJumpMark) then&lt;br /&gt;
        subAddproperty(mFileProperties(), &amp;quot;JumpMark&amp;quot;, sJumpMark)&lt;br /&gt;
end if&lt;br /&gt;
if not isMissing(nViewId) then&lt;br /&gt;
        subAddproperty(mFileProperties(), &amp;quot;ViewId&amp;quot;, nViewId)&lt;br /&gt;
end if&lt;br /&gt;
if not isMissing(bHidden) then&lt;br /&gt;
        subAddproperty(mFileProperties(), &amp;quot;Hidden&amp;quot;, bHidden)&lt;br /&gt;
end if&lt;br /&gt;
if not isMissing(bStartPresentation) then&lt;br /&gt;
        subAddproperty(mFileProperties(), &amp;quot;StartPresentation&amp;quot;, bStartPresentation)&lt;br /&gt;
end if&lt;br /&gt;
if not isMissing(sFilterName) then&lt;br /&gt;
        subAddproperty(mFileProperties(), &amp;quot;FilterName&amp;quot;, sFilterName)&lt;br /&gt;
end if&lt;br /&gt;
if not isMissing(sFilterOptions) then&lt;br /&gt;
        subAddproperty(mFileProperties(), &amp;quot;FilterOptions&amp;quot;, sFilterOptions)&lt;br /&gt;
end if&lt;br /&gt;
if not isMissing(vFilterData) then&lt;br /&gt;
        subAddproperty(mFileProperties(), &amp;quot;FilterData&amp;quot;, vFilterData)&lt;br /&gt;
end if&lt;br /&gt;
if not isMissing(bRepairPackage) then&lt;br /&gt;
        subAddproperty(mFileProperties(), &amp;quot;RepairPackage&amp;quot;, bRepairPackage)&lt;br /&gt;
end if&lt;br /&gt;
sURL = ConvertToURL(sFile)&lt;br /&gt;
on local error resume next&lt;br /&gt;
fnOpenDoc = StarDesktop.loadComponentFromURL(sURL, &amp;quot;_blank&amp;quot;, 0, mFileProperties())&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This function calls subAddProperty which is defined in [[working with properties]]. &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|  &amp;#039;&amp;#039;&amp;#039;Parameter &amp;#039;&amp;#039;&amp;#039;  &lt;br /&gt;
|  &amp;#039;&amp;#039;&amp;#039;Explanation &amp;#039;&amp;#039;&amp;#039;  &lt;br /&gt;
|-&lt;br /&gt;
|bAsTemplate&lt;br /&gt;
|True = Create new document &amp;lt;br&amp;gt; False = Open document (including templates) for editing&lt;br /&gt;
|-&lt;br /&gt;
|sPassword&lt;br /&gt;
|For opening password protected files&lt;br /&gt;
|-&lt;br /&gt;
|bReadOnly&lt;br /&gt;
|True = In the user interface the document will be presented as read only&lt;br /&gt;
|-&lt;br /&gt;
|nMacroExecutionMode&lt;br /&gt;
|com.sun.star.document.MacroExecMode.NEVER_EXECUTE &amp;lt;br&amp;gt; com.sun.star.document.MacroExecMode.ALWAYS_EXECUTE &amp;lt;br&amp;gt; com.sun.star.document.MacroExecMode.ALWAYS_EXECUTE_NO_WARN&lt;br /&gt;
|-&lt;br /&gt;
|nUpdateDocMode&lt;br /&gt;
|com.sun.star.document.UpdateDocMode.NO_UPDATE &amp;lt;br&amp;gt; com.sun.star.document.UpdateDocMode.QUIET_UPDATE &amp;lt;br&amp;gt; com.sun.star.document.UpdateDocMode.ACCORDING_TO_CONFIG &amp;lt;br&amp;gt; com.sun.star.document.UpdateDocMode.FULL_UPDATE&lt;br /&gt;
|-&lt;br /&gt;
|sJumpMark&lt;br /&gt;
|For example the name of a bookmark in a text document&lt;br /&gt;
|-&lt;br /&gt;
|bHidden&lt;br /&gt;
|True = Document opened but not visible. Use with caution&lt;br /&gt;
|-&lt;br /&gt;
|bStartPresentation&lt;br /&gt;
|For Impress documents start the presentation&lt;br /&gt;
|-&lt;br /&gt;
|sFilterName&lt;br /&gt;
|See [[ saving a document]] for a list of filters&lt;br /&gt;
|-&lt;br /&gt;
|sFilterOptions&lt;br /&gt;
|Use this to supply additional info. to the filter&lt;br /&gt;
|-&lt;br /&gt;
|vFilterData&lt;br /&gt;
|Use this if a string for sFilterOptions is insufficient&lt;br /&gt;
|-&lt;br /&gt;
|bRepairPackage&lt;br /&gt;
|True = opens the document in repair mode, so as much information as possible will be retrieved&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
(Does anyone have a good reference for FilterOptions and FilterData?)&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Creating_a_document&amp;diff=9355</id>
		<title>Creating a document</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Creating_a_document&amp;diff=9355"/>
		<updated>2006-05-01T23:59:15Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The following function creates a new document of the specified type in a new window.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnNewDoc(sDocType as string)&lt;br /&gt;
fnNewDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/&amp;quot; &amp;amp; sDocType , &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Examples of calling this function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;swriter&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;scalc&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;simpress&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;sdraw&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;smath&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Currently_open_documents&amp;diff=9354</id>
		<title>Currently open documents</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Currently_open_documents&amp;diff=9354"/>
		<updated>2006-05-01T23:57:25Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;The following function returns an array of the currently open documents. It calls fnWhichComponent which is available from [[Currently active document]].&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnCurrentDocuments(optional sType as string)&lt;br /&gt;
dim oEnum as object, oPosDoc as object, i as integer&lt;br /&gt;
dim oListboxDocs as object&lt;br /&gt;
 &lt;br /&gt;
oEnum = StarDesktop.getComponents.createEnumeration&lt;br /&gt;
 &lt;br /&gt;
&amp;#039;Count windows&lt;br /&gt;
i = -1&lt;br /&gt;
while oEnum.hasMoreElements&lt;br /&gt;
        oPosDoc = oEnum.nextElement&lt;br /&gt;
        &amp;#039; The check for interface XserviceInfo necessary as some windows, e.g. Help&lt;br /&gt;
        &amp;#039; don&amp;#039;t have the interface and need to be excluded anyway.&lt;br /&gt;
        If HasUnoInterfaces(oPosDoc, &amp;quot;com.sun.star.lang.XServiceInfo&amp;quot;) Then&lt;br /&gt;
                if isMissing(sType) then&lt;br /&gt;
                        i = i + 1&lt;br /&gt;
                elseif  fnWhichComponent(oPosDoc) = Stype then&lt;br /&gt;
                        i = i + 1&lt;br /&gt;
                end if&lt;br /&gt;
        end if&lt;br /&gt;
wend&lt;br /&gt;
 &lt;br /&gt;
if i = -1 then&lt;br /&gt;
        &amp;#039;no documents of specified type currently open&lt;br /&gt;
        exit function&lt;br /&gt;
end if&lt;br /&gt;
 &lt;br /&gt;
dim mDocs(i)&lt;br /&gt;
 &lt;br /&gt;
i = -1&lt;br /&gt;
oEnum = StarDesktop.getComponents.createEnumeration&lt;br /&gt;
while oEnum.hasMoreElements&lt;br /&gt;
        oPosDoc = oEnum.nextElement&lt;br /&gt;
        If HasUnoInterfaces( oPosDoc, &amp;quot;com.sun.star.lang.XServiceInfo&amp;quot;) Then &lt;br /&gt;
                If isMissing(sType) then&lt;br /&gt;
                        i = i + 1&lt;br /&gt;
                        mDocs(i) = oPosDoc&lt;br /&gt;
                elseif fnWhichComponent(oPosDoc) = Stype then&lt;br /&gt;
                        i = i + 1&lt;br /&gt;
                        mDocs(i) = oPosDoc&lt;br /&gt;
                end if&lt;br /&gt;
        end if&lt;br /&gt;
wend&lt;br /&gt;
fnCurrentDocuments = mDocs()&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
An example of calling the above function. This function returns an array of the titles for the currently open documents. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnCurrentDocTitles(optional sType as string)&lt;br /&gt;
if isMissing(sType) then&lt;br /&gt;
        mDocs = fnCurrentDocuments()&lt;br /&gt;
else&lt;br /&gt;
        mDocs = fnCurrentDocuments(SType)&lt;br /&gt;
end if&lt;br /&gt;
 &lt;br /&gt;
if isEmpty(mDocs) then&lt;br /&gt;
        exit function&lt;br /&gt;
end if&lt;br /&gt;
 &lt;br /&gt;
nDocs = uBound(mDocs)&lt;br /&gt;
 &lt;br /&gt;
dim mTitles(nDocs)&lt;br /&gt;
 &lt;br /&gt;
for i = 0 to nDocs&lt;br /&gt;
        mTitles(i) = mDocs(i).getCurrentController.getFrame.getPropertyValue(&amp;quot;Title&amp;quot;)&lt;br /&gt;
next&lt;br /&gt;
fnCurrentDocTitles = mTitles()&lt;br /&gt;
End function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
An example of displaying the titles of the currently open documents: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sText = &amp;quot;Text&amp;quot;&lt;br /&gt;
mCurTitles = fnCurrentDocTitles(sText)&lt;br /&gt;
if not isEmpty(mCurTitles) then&lt;br /&gt;
        msgbox join(mCurTitles, chr(10)), 0, &amp;quot;Currently open &amp;quot; &amp;amp; sText &amp;amp; &amp;quot;documents.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
        msgbox &amp;quot;No Text documents currently open.&amp;quot;&lt;br /&gt;
end if&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Currently_active_document&amp;diff=9353</id>
		<title>Currently active document</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Currently_active_document&amp;diff=9353"/>
		<updated>2006-05-01T23:53:31Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;The currently active document can be accessed using thisComponent.&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
An almost equivalent to the BASIC command thisComponent is: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
 StarDesktop.CurrentComponent&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
In OpenOffice.org basic it is generally preferable to use &amp;lt;tt&amp;gt;thisComponent&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
By using &amp;lt;tt&amp;gt;StarDesktop.CurrentComponent&amp;lt;/tt&amp;gt;, a macro in one document can be run on another document. &lt;br /&gt;
&lt;br /&gt;
Another exception is when a routine is run by the OpenOffice.org event &amp;quot;Document Open&amp;quot;. In this case use &amp;lt;tt&amp;gt;StarDesktop.CurrentComponent&amp;lt;/tt&amp;gt; and a check on the document type. The reason for not using &amp;lt;tt&amp;gt;thisComponent&amp;lt;/tt&amp;gt; is that when a library is opened the event fires and thus runs a second time on the currently active document. &lt;br /&gt;
&lt;br /&gt;
To determine the type of document that is currently active you could use the following function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnWhichComponent(oDoc) as string&lt;br /&gt;
if HasUnoInterfaces(oDoc, &amp;quot;com.sun.star.lang.XServiceInfo&amp;quot;) then &lt;br /&gt;
   if thisComponent.supportsService (&amp;quot;com.sun.star.text.GenericTextDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Text&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.sheet.SpreadsheetDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Spreadsheet&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.presentation.PresentationDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Presentation&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.drawing.GenericDrawingDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Drawing&amp;quot;&lt;br /&gt;
   else&lt;br /&gt;
      fnWhichComponent = &amp;quot;Oops current document something else&amp;quot;&lt;br /&gt;
   end if&lt;br /&gt;
else&lt;br /&gt;
   fnWhichComponent = &amp;quot;Not a document&amp;quot;&lt;br /&gt;
end if&lt;br /&gt;
End function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
An example of calling this function is: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
if fnWhichComponent(thisComponent) &amp;lt;&amp;gt; &amp;quot;Text&amp;quot; then&lt;br /&gt;
  msgbox &amp;quot;Sorry - this only works for text documents&amp;quot;, 16, &amp;quot;Error&amp;quot;&lt;br /&gt;
  exit sub&lt;br /&gt;
end if&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Working_with_documents&amp;diff=9352</id>
		<title>Working with documents</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Working_with_documents&amp;diff=9352"/>
		<updated>2006-05-01T23:48:03Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Currently active document]] &lt;br /&gt;
&lt;br /&gt;
[[Currently open documents]] &lt;br /&gt;
&lt;br /&gt;
[[Creating a document]] &lt;br /&gt;
&lt;br /&gt;
[[Opening a document]] &lt;br /&gt;
&lt;br /&gt;
[[Saving a document]] &lt;br /&gt;
&lt;br /&gt;
[[Printing a document]] &lt;br /&gt;
&lt;br /&gt;
[[Closing a document]]&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Working_with_documents&amp;diff=9351</id>
		<title>Working with documents</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Working_with_documents&amp;diff=9351"/>
		<updated>2006-05-01T23:47:20Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;Working with documents &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Currently active document]] &lt;br /&gt;
&lt;br /&gt;
[[Currently open documents]] &lt;br /&gt;
&lt;br /&gt;
[[Creating a document]] &lt;br /&gt;
&lt;br /&gt;
[[Opening a document]] &lt;br /&gt;
&lt;br /&gt;
[[Saving a document]] &lt;br /&gt;
&lt;br /&gt;
[[Printing a document]] &lt;br /&gt;
&lt;br /&gt;
[[Closing a document]]&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=CookBook&amp;diff=9350</id>
		<title>CookBook</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=CookBook&amp;diff=9350"/>
		<updated>2006-05-01T23:45:52Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;Cookbook &amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The material in this tutorial style cookbook builds upon the material covered in [[Extensions_development_basic|Starting in Basic]]. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=General Guides=&lt;br /&gt;
[[Working with documents]] &lt;br /&gt;
&lt;br /&gt;
[[Working with properties]] &lt;br /&gt;
&lt;br /&gt;
[[Sorting and searching]] &lt;br /&gt;
&lt;br /&gt;
[[Working with styles]] &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Component specific guides=&lt;br /&gt;
[[Working with Text Documents]] &lt;br /&gt;
&lt;br /&gt;
[[Working with Spreadsheets]]&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Extensions_development_basic&amp;diff=9349</id>
		<title>Extensions development basic</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Extensions_development_basic&amp;diff=9349"/>
		<updated>2006-05-01T23:39:15Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;Getting started tutorial&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
This page provides a getting started guide for writing macros in OpenOffice.org Basic. It assumes some prior programming knowledge. Please edit this page to make it more readable. I hope you will find it useful.&lt;br /&gt;
&lt;br /&gt;
If you already know the basics then you may want the [[CookBook]] for wrappers and examples.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Where do I write the code?=&lt;br /&gt;
OpenOffice.org Basic code is stored in modules within libraries. A library can be: &lt;br /&gt;
&lt;br /&gt;
*Shared (for a network install - OOo Macros &amp;amp; Dialogs) &lt;br /&gt;
*Just for the current user (My Macros &amp;amp; Dialogs) &lt;br /&gt;
*Within a document or template, so that its code is only available when that document is open.Within a document or template, so that its code is only available when that document is open. &lt;br /&gt;
Libraries not stored in a document or template (that is libraries that are shared or for the current user) are referred to as &amp;#039;&amp;#039;&amp;#039;OpenOffice.org libraries&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
To determine the actual folders that contain the OpenOffice.org libraries see:&amp;lt;br&amp;gt; &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Options… &amp;gt; OpenOffice.org &amp;gt; Paths &amp;gt; BASIC&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|Do not copy or move libraries using operating system commands. Use the macro organizer or package manager instead.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Modules within libraries have a maximum size of 64kb. A library can contain up to 16,000 modules. &lt;br /&gt;
&lt;br /&gt;
For more information see online help for: Modules and Libraries. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Accessing the IDE=&lt;br /&gt;
To access the IDE for the first time: &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org 1.1.x: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Macro… &amp;gt;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org 1.9.x and above: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Organize macros &amp;gt; OpenOffice.org Basic… &amp;gt;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
To get started we will use Module1 in the Standard library which is stored for the current user only: &lt;br /&gt;
&lt;br /&gt;
Type a name for the new macro: &amp;#039;&amp;#039;&amp;#039;HelloWorld&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
In the macro from listbox select &amp;#039;&amp;#039;&amp;#039;Standard&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Click &amp;#039;&amp;#039;&amp;#039;New&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
You should now see something like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
REM  *****  BASIC  *****&lt;br /&gt;
 &lt;br /&gt;
Sub Main&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
 &lt;br /&gt;
Sub HelloWorld&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The cursor will be positioned at the start of the &amp;lt;tt&amp;gt;Sub HelloWorld&amp;lt;/tt&amp;gt; line. &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|Now that while the IDE is running it can be accessed from the OpenOffice.org Window menu, or the task panel provided by the operating system.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Entering the code=&lt;br /&gt;
Select and delete: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
REM  *****  BASIC  *****&lt;br /&gt;
 &lt;br /&gt;
Sub Main&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Below the line &amp;quot;Sub HelloWorld&amp;quot; type &amp;lt;tt&amp;gt;msgbox &amp;quot;Hello World!&amp;quot;&amp;lt;/tt&amp;gt;, so that the editor looks like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Sub HelloWorld&lt;br /&gt;
  msgbox &amp;quot;Hello World!&amp;quot;&lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Notes:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|The IDE does not provide code completion or help with command syntax as you type, but to get help on a Basic command position the cursor in the command and press F1.&amp;lt;br&amp;gt; OpenOffice.org Basic commands are not case sensitive. Thus msgbox, MSGBOX and Msgbox will all work.&amp;lt;br&amp;gt; Strings are enclosed in double quotes.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Running the code=&lt;br /&gt;
There are several ways of running the Basic code, these include: &lt;br /&gt;
&lt;br /&gt;
Directly from the IDE. There is a run button on the macro bar (by default the third control on the second toolbar). This will run the first macro in the current module. &lt;br /&gt;
&lt;br /&gt;
From the tools menu:&lt;br /&gt;
&lt;br /&gt;
(Version 1.1.x) &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Macro…&amp;#039;&amp;#039;&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
(Version 1.9.x and above) &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macro &amp;gt; Run Macro…&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a [[ key press]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a [[ menu entry]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a toolbar button. &lt;br /&gt;
&lt;br /&gt;
Creating a [[ control in a document]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to an event. &lt;br /&gt;
&lt;br /&gt;
For now try running the &amp;quot;HelloWorld&amp;quot; subroutine by clicking the &amp;#039;&amp;#039;&amp;#039;Run&amp;#039;&amp;#039;&amp;#039; button. A small dialog titled &amp;quot;soffice&amp;quot; with the text &amp;quot;Hello World!&amp;quot; and an OK button should be displayed.&lt;br /&gt;
&lt;br /&gt;
=Saving the code=&lt;br /&gt;
The code gets automatically saved whenever the container for the code gets saved. Thus, if the code is in an OpenOffice.org library (shared or users) then it gets automatically saved when OpenOffice.org exits. If the code is in a library which is part of a document it gets saved whenever the document is saved. &lt;br /&gt;
&lt;br /&gt;
On the Standard toolbar (by default the top toolbar) in the IDE there is a save button. If the code is in a document or template then clicking this button saves the entire document or template. If the code is in an OpenOffice.org library then just the current library gets saved. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Variables=&lt;br /&gt;
It is possible to force variable declaration with &amp;lt;tt&amp;gt;Option Explicit&amp;lt;/tt&amp;gt; at the top of the module. For a discussion on whether to declare variables or not see: [[http://www.oooforum.org/forum/viewtopic.phtml?t=5845 this discussion]]. &lt;br /&gt;
&lt;br /&gt;
In that discussion the initial author of this wiki thought that variables should always be declared. Since then he has changed to not declaring them. In short it is generally a personal preference. In either case, it is the initial authors preference that variables be named according to the following convention, which is used in the examples in this Wiki: &lt;br /&gt;
&lt;br /&gt;
The first letter of the variable name indicates the type of value that the variable is going to hold, as per the following table (based on a table in Tutorial.pdf by Sun) &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Letter&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Meaning&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|-&lt;br /&gt;
|a&lt;br /&gt;
|Structure&lt;br /&gt;
|-&lt;br /&gt;
|b&lt;br /&gt;
|Boolean (TRUE or FALSE)&lt;br /&gt;
|-&lt;br /&gt;
|e&lt;br /&gt;
|Enumeration. This variable can only have one of a limited set of values.&lt;br /&gt;
|-&lt;br /&gt;
|f&lt;br /&gt;
|Float (3.402823 x 1038 to 1.401298 x 10-45. A single variable can take up to four bytes)&amp;lt;br&amp;gt; Double (1.79769313486232 x 10308 to 4.94065645841247 x 10-324. A double variable can take up to eight bytes)&amp;lt;br&amp;gt; Currency (-922337203685477.5808 to +922337203685477.5807 and takes up to eight bytes of memory)&lt;br /&gt;
|-&lt;br /&gt;
|m&lt;br /&gt;
|Array (aka sequence aka matrix)&lt;br /&gt;
|-&lt;br /&gt;
|n&lt;br /&gt;
|Integer (-32768 to 32767.) or&amp;lt;br&amp;gt; Long (-2147483648 and 2147483647).&lt;br /&gt;
|-&lt;br /&gt;
|o&lt;br /&gt;
|Object, service, or interface&lt;br /&gt;
|-&lt;br /&gt;
|s&lt;br /&gt;
|String (A string variable can store up to 65535 Unicode characters).&lt;br /&gt;
|-&lt;br /&gt;
|x&lt;br /&gt;
|Interface, to indicate that only operations of a particular interface of an object are used&lt;br /&gt;
|-&lt;br /&gt;
|v&lt;br /&gt;
|Variant, Any&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Use long descriptive variable names making use of camel case &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|User defined OpenOffice.org Basic variables are not case sensitive. But UNO-API constants are case sensitive.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Convention exceptions to long descriptive names is for index variables where i, j, and k are commonly used, and for when a string is being built-up, where s is commonly used. &lt;br /&gt;
&lt;br /&gt;
Edit sub HelloWorld so that it looks like the following and run it: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub HelloWorld&lt;br /&gt;
dim i as integer &amp;#039;This line is optional&lt;br /&gt;
  for i = 0 to 2&lt;br /&gt;
    &amp;#039;These lines are indented for ease of reading only&lt;br /&gt;
    &amp;#039;all your code should be like this for lonog time survival&lt;br /&gt;
    msgbox &amp;quot;Hello World &amp;quot; &amp;amp; i&lt;br /&gt;
  next i&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
For more information on variables see the online help for &amp;quot;using variables&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=Understanding the OpenOffice.org API=&lt;br /&gt;
This section will start with an example. The remainder of this section aims to give information so that the example can be understood and expanded upon. &lt;br /&gt;
&lt;br /&gt;
Try running the following code with different types of documents being active. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
&amp;#039;basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
&amp;#039;xray.xray thisComponent&lt;br /&gt;
msgbox fnWhichComponent(thisComponent)&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function fnWhichComponent(oDoc) as string&lt;br /&gt;
if HasUnoInterfaces(oDoc, &amp;quot;com.sun.star.lang.XServiceInfo&amp;quot;) then &lt;br /&gt;
   if thisComponent.supportsService (&amp;quot;com.sun.star.text.GenericTextDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Text&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.sheet.SpreadsheetDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Spreadsheet&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.presentation.PresentationDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Presentation&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.drawing.GenericDrawingDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Drawing&amp;quot;&lt;br /&gt;
   else&lt;br /&gt;
      fnWhichComponent = &amp;quot;Oops current document something else&amp;quot;&lt;br /&gt;
   end if&lt;br /&gt;
else&lt;br /&gt;
   fnWhichComponent = &amp;quot;Not a document&amp;quot;&lt;br /&gt;
end if&lt;br /&gt;
End function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subroutine naming convention==&lt;br /&gt;
In the above example the user defined function has a name that starts with the letters &amp;quot;fn&amp;quot;. This is the initial authors convention so that people know that this is a user defined function. Similarly, the initial author uses the convention that user defined subroutines start with the letters &amp;quot;sub&amp;quot;. When learning a language and an API it can be difficult to know what is built-in and what has been defined elsewhere. This document/wiki will use this convention for naming functions and subroutines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Introducing the OpenOffice.org API==&lt;br /&gt;
This section introduces the following terms: &lt;br /&gt;
&lt;br /&gt;
* Interface &lt;br /&gt;
* Module &lt;br /&gt;
* Service &lt;br /&gt;
* Method &lt;br /&gt;
* Property &lt;br /&gt;
&lt;br /&gt;
Understanding the difference between an interface and a service and what a module is, is not essential to being able to write extensions for OpenOffice.org, but it does help interpreting the documentation, and for introspection purposes. You may need to read this section at least twice. &lt;br /&gt;
&lt;br /&gt;
An &amp;#039;&amp;#039;&amp;#039;interface&amp;#039;&amp;#039;&amp;#039; is a &amp;#039;&amp;#039;definition&amp;#039;&amp;#039; of a set of methods (and their arguments) that a service which implements that interface must have. &lt;br /&gt;
&lt;br /&gt;
Interfaces are grouped together in &amp;#039;&amp;#039;&amp;#039;modules&amp;#039;&amp;#039;&amp;#039; for naming purposes. All interfaces (and services) start with the name &amp;quot;com.sun.star&amp;quot; then the name of the module then the name of the interface (or service). &lt;br /&gt;
&lt;br /&gt;
For example most services provide the com.sun.star.beans.XPropertySet interface. This interface is stored in the module &amp;quot;beans&amp;quot; and provides access to the properties of a service. A &amp;#039;&amp;#039;&amp;#039;property&amp;#039;&amp;#039;&amp;#039; is a value where as a &amp;#039;&amp;#039;&amp;#039;method&amp;#039;&amp;#039;&amp;#039; is an action. &lt;br /&gt;
&lt;br /&gt;
An OpenOffice.org object can have many services. &lt;br /&gt;
&lt;br /&gt;
An OpenOffice.org object may have a service, which implements an interface, in which a method description says that another OpenOffice.org object is returned.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Introspection==&lt;br /&gt;
HasUnoInterfaces is an OpenOffice.org Basic function for introspection. See this [[http://www.oooforum.org/forum/viewtopic.phtml?t=7068 link]] for information on introspection in other languages. &lt;br /&gt;
&lt;br /&gt;
HasUnoInterfaces returns true if all of the specified interfaces are available for the specified object. &lt;br /&gt;
&lt;br /&gt;
Most OpenOffice.org objects provide the method supportsService because they have the interface com.sun.star.lang.XServiceInfo. &lt;br /&gt;
&lt;br /&gt;
In the above example, the OpenOffice.org Basic command, &amp;#039;&amp;#039;&amp;#039;HasUnoInterfaces&amp;#039;&amp;#039;&amp;#039; checks that the current document has the interface com.sun.star.lang.XServiceInfo, because if it doesn&amp;#039;t have that interface then it doesn&amp;#039;t have the method supportsService, and a run time error would occur if such an object tried to access its nonexistent method. &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;SupportsService&amp;#039;&amp;#039;&amp;#039; is a method which returns true if the specified service is available. The above examples checks for a service to determine the type of document that is currently active.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==X-Ray tool==&lt;br /&gt;
Using HasUnoInterfaces and supportsService gives information about an object at run time, but checking an object like this would be a nightmare for learning? Thankfully Bernard Marcelly has come to our rescue with the X-Ray tool. The X-Ray tool is available from: [[http://ooomacros.org/dev.php#101416 ooomacros]]. Download the zip file, unzip the document, open the document in OpenOffice.org, follow the instructions for installation and set-up. &lt;br /&gt;
&lt;br /&gt;
Part of the X-Ray tool set-up is to specify a local copy of the OpenOffice.org SDK. Download the OpenOffice.org SDK from and extract it. &lt;br /&gt;
&lt;br /&gt;
In the above example, at the start of the code, there are two commented lines (comments start with an apostrophe): &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039;basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
&amp;#039;xray.xray thisComponent&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Now that you have the X-Ray tool installed, uncomment these lines (remove the apostrophes) and rerun the macro. From version 5 of Xray the command simply becomes xray.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;BasicLibraries&amp;#039;&amp;#039;&amp;#039; is an OpenOffice.org Basic command that returns an object for accessing the OpenOffice.org libraries. The &amp;lt;tt&amp;gt;loadLibrary&amp;lt;/tt&amp;gt; method ensures that the routines in that library are available for use. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;xray.xray&amp;lt;/tt&amp;gt; specifies the xray library and the xray subroutine within that library, thisComponent is the object that is being passed to xray for introspection. &lt;br /&gt;
&lt;br /&gt;
To find the object that you want to work with often requires finding or creating it starting from either StarDesktop or thisComponent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Desktop, documents, and current selection==&lt;br /&gt;
StarDesktop and ThisComponent are OpenOffice.org Basic commands that refer to the application and currently active document respectively. &lt;br /&gt;
&lt;br /&gt;
Unlike Microsoft Office, OpenOffice.org is one application with different components. When running some code it maybe useful to check which component is currently active. The above code demonstrates how that checking process can be done. &lt;br /&gt;
&lt;br /&gt;
The Desktop that StarDesktop refers to is conceptual (historically it actually existed) and can be thought of as the OpenOffice.org application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Creating new documents==&lt;br /&gt;
To create a new text document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/swriter&amp;quot;, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To create a new spreadsheet document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/scalc&amp;quot;, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
An easier approach would be to write a simple function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnNewDoc(sDocType as string)&lt;br /&gt;
fnNewDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/&amp;quot; &amp;amp; sDocType , &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Then creating new documents can be achieved with: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;swriter&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;scalc&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;simpress&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;sdraw&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;smath&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
See http://api.openoffice.org/docs/common/ref/com/sun/star/frame/XComponentLoader.html .&lt;br /&gt;
&lt;br /&gt;
==To open a document==&lt;br /&gt;
The following example shows how to open a file. For information on URLs in OpenOffice.org see [[ URL Basics]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sFile = &amp;quot;C:\Documents and Settings\danny\Desktop\MyCalc.sxc&amp;quot; &amp;#039; Windows&lt;br /&gt;
sFile = &amp;quot;/home/danny/Desktop/MyCalc.sxc&amp;quot; &amp;#039; Linux&lt;br /&gt;
sURL = ConvertToURL(sFile)&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(sURL, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Again it may make sense to make this easier by writing a simple function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnOpenDoc(sFile)&lt;br /&gt;
sURL = ConvertToURL(sFile)&lt;br /&gt;
fnOpenDoc = StarDesktop.loadComponentFromURL(sURL, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Examples of calling the function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = fnOpenDoc(&amp;quot;C:\Documents and Settings\danny\Desktop\MyCalc.sxc&amp;quot;) &amp;#039; Windows&lt;br /&gt;
oDoc = fnOpenDoc(&amp;quot;/home/danny/Desktop/MyCalc.sxc&amp;quot;) &amp;#039; Linux&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Current Selection==&lt;br /&gt;
It is common to want to run some code that effects the current selection. &amp;lt;tt&amp;gt;ThisComponent&amp;lt;/tt&amp;gt; has the method &amp;lt;tt&amp;gt;getCurrentSelection&amp;lt;/tt&amp;gt;. Since many different types of objects could possibly be selected it is common to check that the currently selected object has the service that contains the method that we want to apply to the object. &lt;br /&gt;
&lt;br /&gt;
Edit the main subroutine to the following and rerun it on a text document with different selections. (To select more than one block of text hold down the control key). &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
if fnWhichComponent(thisComponent) = &amp;quot;Text&amp;quot; then&lt;br /&gt;
        oCurSelection = thisComponent.getCurrentSelection()&lt;br /&gt;
        &amp;#039;xray.xray oCurSelection&lt;br /&gt;
        if oCurSelection.supportsService(&amp;quot;com.sun.star.text.TextRanges&amp;quot;) then&lt;br /&gt;
                msgbox &amp;quot;There are &amp;quot; &amp;amp; oCurSelection.getCount() &amp;amp; _&lt;br /&gt;
                 &amp;quot; selections in the current text document.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
With nothing selected the number of selections is one - the insertion point, with one block of text selected the count is still one, but with two blocks of text the count is three - the insertion point and the two blocks of selected text. &lt;br /&gt;
&lt;br /&gt;
Exercise 1: Modify the above code so that it works on selected cell ranges in a spreadsheet. &lt;br /&gt;
&lt;br /&gt;
Question1: For two blocks of cells selected, what would be the count for the number of selections? &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Properties==&lt;br /&gt;
Uncomment &amp;lt;tt&amp;gt;&amp;#039;xray.xray oCurSelection&amp;lt;/tt&amp;gt; so that xray runs, to see that the object that &amp;lt;tt&amp;gt;oCurSelection&amp;lt;/tt&amp;gt; points to has a &amp;quot;property&amp;quot; called &amp;lt;tt&amp;gt;Count&amp;lt;/tt&amp;gt; with a description of &amp;quot;pseudo-prop, read only&amp;quot;. It is possible in OpenOffice.org Basic to write &amp;lt;tt&amp;gt;oCurSelection.count&amp;lt;/tt&amp;gt;, but as this is not possible in all other languages accessing the OpenOffice.org API, this Wiki will try to always use the method approach. (I say try because I have not been in the habit of doing this and sometimes I may forget). &lt;br /&gt;
&lt;br /&gt;
This next example demonstrates changing a property value for the current selections. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
if fnWhichComponent(thisComponent) = &amp;quot;Text&amp;quot; then&lt;br /&gt;
   oCurSelection = thisComponent.getCurrentSelection()&lt;br /&gt;
   if oCurSelection.supportsService(&amp;quot;com.sun.star.text.TextRanges&amp;quot;) then&lt;br /&gt;
      nCount = oCurSelection.Count&lt;br /&gt;
      &amp;#039;xray.xray oCurSelection.getByIndex(0)&lt;br /&gt;
      &amp;#039;Warning: The insertion point will have the same action applied twice&lt;br /&gt;
      &amp;#039;in this case it doesn&amp;#039;t matter, but in others it might.&lt;br /&gt;
      for i = 0 to nCount - 1&lt;br /&gt;
         oCurSelection.getByIndex(i).setPropertyValue(&amp;quot;CharStyleName&amp;quot;, &amp;quot;Strong Emphasis&amp;quot;)&lt;br /&gt;
      next&lt;br /&gt;
   end if&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
In OpenOffice.org Basic it is possible to shorten the assignment line to: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oCurSelection(i).CharStyleName = &amp;quot;Strong Emphasis&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This wiki will try to use the full methods for both indexing and assigning properties. The rationale is that this makes converting the code to other languages easier and also helps the learner to understand what is happening (again I have not been in the habit of doing this so some examples may slip past me). &lt;br /&gt;
&lt;br /&gt;
Exercise 2: Rewrite the above code so that the warning can be removed. &lt;br /&gt;
&lt;br /&gt;
See [[ Current selection]]. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Iterative Access to Subordinate Objects (Enumeration access)=&lt;br /&gt;
Sometimes to access the desired object an enumeration is required. For example paragraphs, within a document or within a selection. &lt;br /&gt;
&lt;br /&gt;
When a Writer document is active and some text is selected, both &amp;lt;tt&amp;gt;thisDocument.getText()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;thisComponent.getCurrentSelection().getByIndex(i)&amp;lt;/tt&amp;gt; have the service: com.sun.star.text.TextRange which has the interface: com.sun.star.container.XContentEnumerationAccess, it is possible to create an enumeration of the paragraphs for the current document or for a particular selection. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; Create enumeration object&lt;br /&gt;
oTextElementEnum = thisComponent.getText().createEnumeration()&lt;br /&gt;
&amp;#039;or thisComponent.getCurrentSelection().getByIndex(i).createEnumeration()&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; loop over all text elements&lt;br /&gt;
while oTextElementEnum.hasMoreElements()&lt;br /&gt;
        oTextElement = oTextElementEnum.nextElement&lt;br /&gt;
        if oTextElement.supportsService(&amp;quot;com.sun.star.text.TextTable&amp;quot;) then&lt;br /&gt;
                MsgBox &amp;quot;The current block contains a table.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
        if oTextElement.supportsService(&amp;quot;com.sun.star.text.Paragraph&amp;quot;) then&lt;br /&gt;
                MsgBox &amp;quot;The current block contains a paragraph.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
wend&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Exercise 3: Extend the above example to display in a message box all text portions that are bold. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Named access=&lt;br /&gt;
Some objects provide named access to a particular type of subordinate object, some others indexed access, and some both named and indexed access. &lt;br /&gt;
&lt;br /&gt;
For example if the current document in OpenOffice.org is a spreadsheet then to access a particular sheet can be done by index access: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oSheet = thisComponent.getSheets.getByIndex(0)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
or named access: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oSheet = thisComponent.getSheets.getByName(&amp;quot;Sheet1&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To check if an object with a particular name already exists use &amp;lt;tt&amp;gt;hasByName&amp;lt;/tt&amp;gt;, for example: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
if thisComponent.getSheets.hasByName(&amp;quot;Sheet1&amp;quot;) then&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To loop through all the available object names can be done like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
mNames = thisComponent.getSheets.getElementnames&lt;br /&gt;
for i = lbound(mNames) to ubound(mNames)&lt;br /&gt;
        msgbox mNames(i)&lt;br /&gt;
next&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Some named subordinate objects also provide the interface:  com.sun.star.container.XNameContainer. This interface defines that such objects should have the following methods: &amp;lt;tt&amp;gt;insertByName&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;replaceByname&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;removeByName&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
E.g. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
thisComponent.getSheets.insertByName(&amp;quot;NewSheet&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Create new objects=&lt;br /&gt;
Some objects have services which implement interfaces to provide specific methods for creating a particular type of object. &lt;br /&gt;
&lt;br /&gt;
For example if the current document is a Writer document then &amp;lt;tt&amp;gt;thisComponent.getText&amp;lt;/tt&amp;gt; is an object that provides the service com.sun.star.text.Text which implements the interface  com.sun.star.text.XSimpleText which defines the methods &amp;lt;tt&amp;gt;createTextCursor&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;createTextCursorByRange&amp;lt;/tt&amp;gt;. Both of these methods create a text cursor for accessing the text of the document. These cursors are quite independent of the view cursor . The view cursor is visible on the screen and is manipulated by the user (and can be manipulated by program control), where as a text cursor is not visible on the screen and is solely used by program control. The following code snippet demonstrates creating a new text cursor, such that it starts at the same location as the viewCursor and is then moved independent of the view cursor. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oVC = thisComponent.getCurrentController.getViewCursor&lt;br /&gt;
oCursor = oVC.getText.createTextCursorByRange(oVC)&lt;br /&gt;
oCursor.gotoStartOfSentence(false)&lt;br /&gt;
oCursor.gotoEndOfSentence(true)&lt;br /&gt;
msgbox oCursor.getString&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Some objects are context dependent and get created using the method &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt; which is defined in the interface com.sun.star.lang.XMultiServiceFactory. For example to add a rectangle to the first page of a drawing document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
dim aPoint as new com.sun.star.awt.Point&lt;br /&gt;
dim aSize as new com.sun.star.awt.Size&lt;br /&gt;
 &lt;br /&gt;
aPoint.x = 1000&lt;br /&gt;
aPoint.y = 1000&lt;br /&gt;
 &lt;br /&gt;
aSize.Width = 10000&lt;br /&gt;
aSize.Height = 10000&lt;br /&gt;
 &lt;br /&gt;
oRectangleShape = thisComponent.createInstance(&amp;quot;com.sun.star.drawing.RectangleShape&amp;quot;)&lt;br /&gt;
oRectangleShape.Size = aSize&lt;br /&gt;
oRectangleShape.Position = aPoint&lt;br /&gt;
 &lt;br /&gt;
thisComponent.getDrawPages.getByIndex(0).add(oRectangleShape)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example also uses UNO structs see below for more information on UNO stucts. &lt;br /&gt;
&lt;br /&gt;
Some objects are context independent to create these objects use the OpenOffice.org Basic command createUnoService. For example to create the equivalent to StarDesktop: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDesktop = createUnoService(&amp;quot;com.sun.star.frame.Desktop&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The process that I use to determine how to access or create an object is as follows: &lt;br /&gt;
&lt;br /&gt;
Does the object already exist if so I should be able to access it from something like &amp;lt;tt&amp;gt;thisComponent&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Will the new object belong to another object, if so does the owner have a specific method for creating the object, if so use it. &lt;br /&gt;
&lt;br /&gt;
The new object will belong to another object, but that object doesn&amp;#039;t provide a specific method for creating it, but does provide &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt;. If the object doesn&amp;#039;t provide &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt; are you sure you are using the correct object, or is it context independent. &lt;br /&gt;
&lt;br /&gt;
I have found working out how to create an object to be quite difficult with existing documentation so I hope that this document/wiki will eventually make this clear. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==UNO structs==&lt;br /&gt;
UNO structures can be declared using the OpenOffice.org Basic command &amp;lt;tt&amp;gt;dim&amp;lt;/tt&amp;gt;: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
dim aPoint as new com.sun.star.awt.Point&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Or by using the OpenOffice.org Basic command &amp;lt;tt&amp;gt;createUnoStruct&amp;lt;/tt&amp;gt;: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
aPoint = createUnoStruct(&amp;quot;com.sun.star.awt.Point&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|When declaring UNO structs case is important. Note that everything upto the name of the struct is lowercase, and that the name of the struct is in TitleCase.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Creating Listeners and Handlers==&lt;br /&gt;
Through the user interface it is possible to assign macros to some events: &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org versions 1.1.x: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Configure… &amp;gt; Events&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org versions 1.9.x and above: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Customize… &amp;gt; Events&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
It is also possible to assign macros to a wider range of events using the OpenOffice.org Basic command CreateUnoListener. This same command is used for creating both listeners and handlers. A listener checks for an event and always allows other listeners to respond to the event as well. A handler listens for an event, and can optionally consume the event so that other listeners don&amp;#039;t get to act on it. &lt;br /&gt;
&lt;br /&gt;
The following example creates a keyHandler: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
global IannzExampleKeyHandler&lt;br /&gt;
 &lt;br /&gt;
sub SetupKeyHandler&lt;br /&gt;
oController = thisComponent.currentController&lt;br /&gt;
IannzExampleKeyHandler = CreateUnoListener(&amp;quot;KeyHandler_&amp;quot;,&amp;quot;com.sun.star.awt.XKeyHandler&amp;quot;)&lt;br /&gt;
oController.addKeyHandler(IannzExampleKeyHandler) &amp;#039; Register the listener&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
sub RemoveKeyHandler&lt;br /&gt;
thisComponent.currentController.removeKeyHandler(IannzExampleKeyHandler)&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
sub KeyHandler_disposing&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function KeyHandler_keyReleased(oKeyEvent as new com.sun.star.awt.KeyHandler) as boolean&lt;br /&gt;
        KeyHandler_keyReleased = False    &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function KeyHandler_keyPressed(oKeyEvent as new com.sun.star.awt.KeyHandler) as boolean&lt;br /&gt;
KeyHandler_keyPressed = false   &amp;#039;Let other listeners handle the event&lt;br /&gt;
if oKeyEvent.modifiers = com.sun.star.awt.KeyModifier.MOD2 then &amp;#039;Control key was pressed&lt;br /&gt;
        if oKeyEvent.keyCode = com.sun.star.awt.Key.Q then&lt;br /&gt;
                msgbox &amp;quot;Alt + Q was pressed&amp;quot;&lt;br /&gt;
                KeyHandler_keyPressed = true    &amp;#039;Don&amp;#039;t let other listeners process this event&lt;br /&gt;
        end if&lt;br /&gt;
end if&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
A variable declared as global keeps its value even after the macro exits. In this case we want to be able to use this variable later to remove the handler. As variables declared globally could be used in other libraries to try and avoid conflict I start all my global variables with Iannz my registered name for the OpenOffice.org web site. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;sub SetupKeyHandler&amp;lt;/tt&amp;gt; sets up the handler. The first parameter to CreateUnoListener is the staring name for the methods that will be called when that type of event occurs in this example .&amp;lt;tt&amp;gt;&amp;quot;KeyHandler_&amp;quot;&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
The second parameter is the name of the interface for the listener or handler, &amp;quot;com.sun.star.awt.XKeyHandler&amp;quot;. The name is case sensitive, everything up to and including the module name is always lowercase, the name of the interface always starts with &amp;quot;X&amp;quot; and the remainder is in TitleCase. &lt;br /&gt;
&lt;br /&gt;
Use the SDK to find out what methods the interface must supply. You must supply routines for all of these methods even if you don&amp;#039;t intend to use them. You also need to supply a disposing method. The names of these routines start with the string given in the first parameter to CreateUnoListener , in this example &amp;lt;tt&amp;gt;&amp;quot;KeyHandler_&amp;quot;&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Thus in the example there is &amp;lt;tt&amp;gt;KeyHandler_disposing&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;KeyHandler_keyReleased&amp;lt;/tt&amp;gt; which don&amp;#039;t actually do anything but are required, and &amp;lt;tt&amp;gt;KeyHandler_keyPressed&amp;lt;/tt&amp;gt; which actually does the job. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;sub RemoveKeyHandler&amp;lt;/tt&amp;gt; demonstrates how to remove the handler.&lt;br /&gt;
&lt;br /&gt;
=OpenOffice.org constants=&lt;br /&gt;
The above example uses OpenOffice.org constants. &lt;br /&gt;
&lt;br /&gt;
E.g. com.sun.star.awt.KeyModifier.MOD2&lt;br /&gt;
&lt;br /&gt;
OpenOffice.org constants are case sensitive. Everything up to and including the module name is always lowercase. The constant group is in TitleCase. The actual constant name is always UPPERCASE. &lt;br /&gt;
&lt;br /&gt;
Programmers not using OpenOffice.org Basic may not have access to these constants. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Using the recorder=&lt;br /&gt;
See [[ The OpenOffice.org recorder and UNO dispatch calls]] section for a discussion on recording UNO Dispatch commands versus writing API calls.&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Extensions_development_basic&amp;diff=9303</id>
		<title>Extensions development basic</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Extensions_development_basic&amp;diff=9303"/>
		<updated>2006-05-01T03:35:57Z</updated>

		<summary type="html">&lt;p&gt;Iannz: /* Running the code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;Getting started tutorial&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
This page provides a getting started guide for writing macros in OpenOffice.org Basic. It assumes some prior programming knowledge. Please edit this page to make it more readable. I hope you will find it useful in getting started.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Where do I write the code?=&lt;br /&gt;
OpenOffice.org Basic code is stored in modules within libraries. A library can be: &lt;br /&gt;
&lt;br /&gt;
*Shared (for a network install - OOo Macros &amp;amp; Dialogs) &lt;br /&gt;
*Just for the current user (My Macros &amp;amp; Dialogs) &lt;br /&gt;
*Within a document or template, so that its code is only available when that document is open.Within a document or template, so that its code is only available when that document is open. &lt;br /&gt;
Libraries not stored in a document or template (that is libraries that are shared or for the current user) are referred to as &amp;#039;&amp;#039;&amp;#039;OpenOffice.org libraries&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
To determine the actual folders that contain the OpenOffice.org libraries see:&amp;lt;br&amp;gt; &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Options… &amp;gt; OpenOffice.org &amp;gt; Paths &amp;gt; BASIC&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|Do not copy or move libraries using operating system commands. Use the macro organizer or package manager instead.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Modules within libraries have a maximum size of 64kb. A library can contain up to 16,000 modules. &lt;br /&gt;
&lt;br /&gt;
For more information see online help for: Modules and Libraries. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Accessing the IDE=&lt;br /&gt;
To access the IDE for the first time: &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org 1.1.x: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Macro… &amp;gt;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org 1.9.x and above: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Organize macros &amp;gt; OpenOffice.org Basic… &amp;gt;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
To get started we will use Module1 in the Standard library which is stored for the current user only: &lt;br /&gt;
&lt;br /&gt;
Type a name for the new macro: &amp;#039;&amp;#039;&amp;#039;HelloWorld&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
In the macro from listbox select &amp;#039;&amp;#039;&amp;#039;Standard&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Click &amp;#039;&amp;#039;&amp;#039;New&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
You should now see something like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
REM  *****  BASIC  *****&lt;br /&gt;
 &lt;br /&gt;
Sub Main&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
 &lt;br /&gt;
Sub HelloWorld&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The cursor will be positioned at the start of the &amp;lt;tt&amp;gt;Sub HelloWorld&amp;lt;/tt&amp;gt; line. &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|Now that while the IDE is running it can be accessed from the OpenOffice.org Window menu, or the task panel provided by the operating system.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Entering the code=&lt;br /&gt;
Select and delete: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
REM  *****  BASIC  *****&lt;br /&gt;
 &lt;br /&gt;
Sub Main&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Below the line &amp;quot;Sub HelloWorld&amp;quot; type &amp;lt;tt&amp;gt;msgbox &amp;quot;Hello World!&amp;quot;&amp;lt;/tt&amp;gt;, so that the editor looks like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Sub HelloWorld&lt;br /&gt;
  msgbox &amp;quot;Hello World!&amp;quot;&lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Notes:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|The IDE does not provide code completion or help with command syntax as you type, but to get help on a Basic command position the cursor in the command and press F1.&amp;lt;br&amp;gt; OpenOffice.org Basic commands are not case sensitive. Thus msgbox, MSGBOX and Msgbox will all work.&amp;lt;br&amp;gt; Strings are enclosed in double quotes.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Running the code=&lt;br /&gt;
There are several ways of running the Basic code, these include: &lt;br /&gt;
&lt;br /&gt;
Directly from the IDE. There is a run button on the macro bar (by default the third control on the second toolbar). This will run the first macro in the current module. &lt;br /&gt;
&lt;br /&gt;
From the tools menu:&lt;br /&gt;
&lt;br /&gt;
(Version 1.1.x) &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Macro…&amp;#039;&amp;#039;&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
(Version 1.9.x and above) &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macro &amp;gt; Run Macro…&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a [[ key press]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a [[ menu entry]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a toolbar button. &lt;br /&gt;
&lt;br /&gt;
Creating a [[ control in a document]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to an event. &lt;br /&gt;
&lt;br /&gt;
For now try running the &amp;quot;HelloWorld&amp;quot; subroutine by clicking the &amp;#039;&amp;#039;&amp;#039;Run&amp;#039;&amp;#039;&amp;#039; button. A small dialog titled &amp;quot;soffice&amp;quot; with the text &amp;quot;Hello World!&amp;quot; and an OK button should be displayed.&lt;br /&gt;
&lt;br /&gt;
=Saving the code=&lt;br /&gt;
The code gets automatically saved whenever the container for the code gets saved. Thus, if the code is in an OpenOffice.org library (shared or users) then it gets automatically saved when OpenOffice.org exits. If the code is in a library which is part of a document it gets saved whenever the document is saved. &lt;br /&gt;
&lt;br /&gt;
On the Standard toolbar (by default the top toolbar) in the IDE there is a save button. If the code is in a document or template then clicking this button saves the entire document or template. If the code is in an OpenOffice.org library then just the current library gets saved. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Variables=&lt;br /&gt;
It is possible to force variable declaration with &amp;lt;tt&amp;gt;Option Explicit&amp;lt;/tt&amp;gt; at the top of the module. For a discussion on whether to declare variables or not see: [[http://www.oooforum.org/forum/viewtopic.phtml?t=5845 this discussion]]. &lt;br /&gt;
&lt;br /&gt;
In that discussion the initial author of this wiki thought that variables should always be declared. Since then he has changed to not declaring them. In short it is generally a personal preference. In either case, it is the initial authors preference that variables be named according to the following convention, which is used in the examples in this Wiki: &lt;br /&gt;
&lt;br /&gt;
The first letter of the variable name indicates the type of value that the variable is going to hold, as per the following table (based on a table in Tutorial.pdf by Sun) &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Letter&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Meaning&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|-&lt;br /&gt;
|a&lt;br /&gt;
|Structure&lt;br /&gt;
|-&lt;br /&gt;
|b&lt;br /&gt;
|Boolean (TRUE or FALSE)&lt;br /&gt;
|-&lt;br /&gt;
|e&lt;br /&gt;
|Enumeration. This variable can only have one of a limited set of values.&lt;br /&gt;
|-&lt;br /&gt;
|f&lt;br /&gt;
|Float (3.402823 x 1038 to 1.401298 x 10-45. A single variable can take up to four bytes)&amp;lt;br&amp;gt; Double (1.79769313486232 x 10308 to 4.94065645841247 x 10-324. A double variable can take up to eight bytes)&amp;lt;br&amp;gt; Currency (-922337203685477.5808 to +922337203685477.5807 and takes up to eight bytes of memory)&lt;br /&gt;
|-&lt;br /&gt;
|m&lt;br /&gt;
|Array (aka sequence aka matrix)&lt;br /&gt;
|-&lt;br /&gt;
|n&lt;br /&gt;
|Integer (-32768 to 32767.) or&amp;lt;br&amp;gt; Long (-2147483648 and 2147483647).&lt;br /&gt;
|-&lt;br /&gt;
|o&lt;br /&gt;
|Object, service, or interface&lt;br /&gt;
|-&lt;br /&gt;
|s&lt;br /&gt;
|String (A string variable can store up to 65535 Unicode characters).&lt;br /&gt;
|-&lt;br /&gt;
|x&lt;br /&gt;
|Interface, to indicate that only operations of a particular interface of an object are used&lt;br /&gt;
|-&lt;br /&gt;
|v&lt;br /&gt;
|Variant, Any&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Use long descriptive variable names making use of camel case &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|User defined OpenOffice.org Basic variables are not case sensitive. But UNO-API constants are case sensitive.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Convention exceptions to long descriptive names is for index variables where i, j, and k are commonly used, and for when a string is being built-up, where s is commonly used. &lt;br /&gt;
&lt;br /&gt;
Edit sub HelloWorld so that it looks like the following and run it: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub HelloWorld&lt;br /&gt;
dim i as integer &amp;#039;This line is optional&lt;br /&gt;
  for i = 0 to 2&lt;br /&gt;
    &amp;#039;These lines are indented for ease of reading only&lt;br /&gt;
    &amp;#039;all your code should be like this for lonog time survival&lt;br /&gt;
    msgbox &amp;quot;Hello World &amp;quot; &amp;amp; i&lt;br /&gt;
  next i&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
For more information on variables see the online help for &amp;quot;using variables&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=Understanding the OpenOffice.org API=&lt;br /&gt;
This section will start with an example. The remainder of this section aims to give information so that the example can be understood and expanded upon. &lt;br /&gt;
&lt;br /&gt;
Try running the following code with different types of documents being active. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
&amp;#039;basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
&amp;#039;xray.xray thisComponent&lt;br /&gt;
msgbox fnWhichComponent(thisComponent)&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function fnWhichComponent(oDoc) as string&lt;br /&gt;
if HasUnoInterfaces(oDoc, &amp;quot;com.sun.star.lang.XServiceInfo&amp;quot;) then &lt;br /&gt;
   if thisComponent.supportsService (&amp;quot;com.sun.star.text.GenericTextDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Text&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.sheet.SpreadsheetDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Spreadsheet&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.presentation.PresentationDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Presentation&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.drawing.GenericDrawingDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Drawing&amp;quot;&lt;br /&gt;
   else&lt;br /&gt;
      fnWhichComponent = &amp;quot;Oops current document something else&amp;quot;&lt;br /&gt;
   end if&lt;br /&gt;
else&lt;br /&gt;
   fnWhichComponent = &amp;quot;Not a document&amp;quot;&lt;br /&gt;
end if&lt;br /&gt;
End function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subroutine naming convention==&lt;br /&gt;
In the above example the user defined function has a name that starts with the letters &amp;quot;fn&amp;quot;. This is the initial authors convention so that people know that this is a user defined function. Similarly, the initial author uses the convention that user defined subroutines start with the letters &amp;quot;sub&amp;quot;. When learning a language and an API it can be difficult to know what is built-in and what has been defined elsewhere. This document/wiki will use this convention for naming functions and subroutines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Introducing the OpenOffice.org API==&lt;br /&gt;
This section introduces the following terms: &lt;br /&gt;
&lt;br /&gt;
* Interface &lt;br /&gt;
* Module &lt;br /&gt;
* Service &lt;br /&gt;
* Method &lt;br /&gt;
* Property &lt;br /&gt;
&lt;br /&gt;
Understanding the difference between an interface and a service and what a module is, is not essential to being able to write extensions for OpenOffice.org, but it does help interpreting the documentation, and for introspection purposes. You may need to read this section at least twice. &lt;br /&gt;
&lt;br /&gt;
An &amp;#039;&amp;#039;&amp;#039;interface&amp;#039;&amp;#039;&amp;#039; is a &amp;#039;&amp;#039;definition&amp;#039;&amp;#039; of a set of methods (and their arguments) that a service which implements that interface must have. &lt;br /&gt;
&lt;br /&gt;
Interfaces are grouped together in &amp;#039;&amp;#039;&amp;#039;modules&amp;#039;&amp;#039;&amp;#039; for naming purposes. All interfaces (and services) start with the name &amp;quot;com.sun.star&amp;quot; then the name of the module then the name of the interface (or service). &lt;br /&gt;
&lt;br /&gt;
For example most services provide the com.sun.star.beans.XPropertySet interface. This interface is stored in the module &amp;quot;beans&amp;quot; and provides access to the properties of a service. A &amp;#039;&amp;#039;&amp;#039;property&amp;#039;&amp;#039;&amp;#039; is a value where as a &amp;#039;&amp;#039;&amp;#039;method&amp;#039;&amp;#039;&amp;#039; is an action. &lt;br /&gt;
&lt;br /&gt;
An OpenOffice.org object can have many services. &lt;br /&gt;
&lt;br /&gt;
An OpenOffice.org object may have a service, which implements an interface, in which a method description says that another OpenOffice.org object is returned.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Introspection==&lt;br /&gt;
HasUnoInterfaces is an OpenOffice.org Basic function for introspection. See this [[http://www.oooforum.org/forum/viewtopic.phtml?t=7068 link]] for information on introspection in other languages. &lt;br /&gt;
&lt;br /&gt;
HasUnoInterfaces returns true if all of the specified interfaces are available for the specified object. &lt;br /&gt;
&lt;br /&gt;
Most OpenOffice.org objects provide the method supportsService because they have the interface com.sun.star.lang.XServiceInfo. &lt;br /&gt;
&lt;br /&gt;
In the above example, the OpenOffice.org Basic command, &amp;#039;&amp;#039;&amp;#039;HasUnoInterfaces&amp;#039;&amp;#039;&amp;#039; checks that the current document has the interface com.sun.star.lang.XServiceInfo, because if it doesn&amp;#039;t have that interface then it doesn&amp;#039;t have the method supportsService, and a run time error would occur if such an object tried to access its nonexistent method. &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;SupportsService&amp;#039;&amp;#039;&amp;#039; is a method which returns true if the specified service is available. The above examples checks for a service to determine the type of document that is currently active.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==X-Ray tool==&lt;br /&gt;
Using HasUnoInterfaces and supportsService gives information about an object at run time, but checking an object like this would be a nightmare for learning? Thankfully Bernard Marcelly has come to our rescue with the X-Ray tool. The X-Ray tool is available from: [[http://ooomacros.org/dev.php#101416 ooomacros]]. Download the zip file, unzip the document, open the document in OpenOffice.org, follow the instructions for installation and set-up. &lt;br /&gt;
&lt;br /&gt;
Part of the X-Ray tool set-up is to specify a local copy of the OpenOffice.org SDK. Download the OpenOffice.org SDK from and extract it. &lt;br /&gt;
&lt;br /&gt;
In the above example, at the start of the code, there are two commented lines (comments start with an apostrophe): &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039;basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
&amp;#039;xray.xray thisComponent&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Now that you have the X-Ray tool installed, uncomment these lines (remove the apostrophes) and rerun the macro. From version 5 of Xray the command simply becomes xray.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;BasicLibraries&amp;#039;&amp;#039;&amp;#039; is an OpenOffice.org Basic command that returns an object for accessing the OpenOffice.org libraries. The &amp;lt;tt&amp;gt;loadLibrary&amp;lt;/tt&amp;gt; method ensures that the routines in that library are available for use. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;xray.xray&amp;lt;/tt&amp;gt; specifies the xray library and the xray subroutine within that library, thisComponent is the object that is being passed to xray for introspection. &lt;br /&gt;
&lt;br /&gt;
To find the object that you want to work with often requires finding or creating it starting from either StarDesktop or thisComponent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Desktop, documents, and current selection==&lt;br /&gt;
StarDesktop and ThisComponent are OpenOffice.org Basic commands that refer to the application and currently active document respectively. &lt;br /&gt;
&lt;br /&gt;
Unlike Microsoft Office, OpenOffice.org is one application with different components. When running some code it maybe useful to check which component is currently active. The above code demonstrates how that checking process can be done. &lt;br /&gt;
&lt;br /&gt;
The Desktop that StarDesktop refers to is conceptual (historically it actually existed) and can be thought of as the OpenOffice.org application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Creating new documents==&lt;br /&gt;
To create a new text document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/swriter&amp;quot;, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To create a new spreadsheet document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/scalc&amp;quot;, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
An easier approach would be to write a simple function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnNewDoc(sDocType as string)&lt;br /&gt;
fnNewDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/&amp;quot; &amp;amp; sDocType , &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Then creating new documents can be achieved with: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;swriter&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;scalc&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;simpress&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;sdraw&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;smath&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
See http://api.openoffice.org/docs/common/ref/com/sun/star/frame/XComponentLoader.html .&lt;br /&gt;
&lt;br /&gt;
==To open a document==&lt;br /&gt;
The following example shows how to open a file. For information on URLs in OpenOffice.org see [[ URL Basics]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sFile = &amp;quot;C:\Documents and Settings\danny\Desktop\MyCalc.sxc&amp;quot; &amp;#039; Windows&lt;br /&gt;
sFile = &amp;quot;/home/danny/Desktop/MyCalc.sxc&amp;quot; &amp;#039; Linux&lt;br /&gt;
sURL = ConvertToURL(sFile)&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(sURL, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Again it may make sense to make this easier by writing a simple function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnOpenDoc(sFile)&lt;br /&gt;
sURL = ConvertToURL(sFile)&lt;br /&gt;
fnOpenDoc = StarDesktop.loadComponentFromURL(sURL, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Examples of calling the function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = fnOpenDoc(&amp;quot;C:\Documents and Settings\danny\Desktop\MyCalc.sxc&amp;quot;) &amp;#039; Windows&lt;br /&gt;
oDoc = fnOpenDoc(&amp;quot;/home/danny/Desktop/MyCalc.sxc&amp;quot;) &amp;#039; Linux&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Current Selection==&lt;br /&gt;
It is common to want to run some code that effects the current selection. &amp;lt;tt&amp;gt;ThisComponent&amp;lt;/tt&amp;gt; has the method &amp;lt;tt&amp;gt;getCurrentSelection&amp;lt;/tt&amp;gt;. Since many different types of objects could possibly be selected it is common to check that the currently selected object has the service that contains the method that we want to apply to the object. &lt;br /&gt;
&lt;br /&gt;
Edit the main subroutine to the following and rerun it on a text document with different selections. (To select more than one block of text hold down the control key). &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
if fnWhichComponent(thisComponent) = &amp;quot;Text&amp;quot; then&lt;br /&gt;
        oCurSelection = thisComponent.getCurrentSelection()&lt;br /&gt;
        &amp;#039;xray.xray oCurSelection&lt;br /&gt;
        if oCurSelection.supportsService(&amp;quot;com.sun.star.text.TextRanges&amp;quot;) then&lt;br /&gt;
                msgbox &amp;quot;There are &amp;quot; &amp;amp; oCurSelection.getCount() &amp;amp; _&lt;br /&gt;
                 &amp;quot; selections in the current text document.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
With nothing selected the number of selections is one - the insertion point, with one block of text selected the count is still one, but with two blocks of text the count is three - the insertion point and the two blocks of selected text. &lt;br /&gt;
&lt;br /&gt;
Exercise 1: Modify the above code so that it works on selected cell ranges in a spreadsheet. &lt;br /&gt;
&lt;br /&gt;
Question1: For two blocks of cells selected, what would be the count for the number of selections? &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Properties==&lt;br /&gt;
Uncomment &amp;lt;tt&amp;gt;&amp;#039;xray.xray oCurSelection&amp;lt;/tt&amp;gt; so that xray runs, to see that the object that &amp;lt;tt&amp;gt;oCurSelection&amp;lt;/tt&amp;gt; points to has a &amp;quot;property&amp;quot; called &amp;lt;tt&amp;gt;Count&amp;lt;/tt&amp;gt; with a description of &amp;quot;pseudo-prop, read only&amp;quot;. It is possible in OpenOffice.org Basic to write &amp;lt;tt&amp;gt;oCurSelection.count&amp;lt;/tt&amp;gt;, but as this is not possible in all other languages accessing the OpenOffice.org API, this Wiki will try to always use the method approach. (I say try because I have not been in the habit of doing this and sometimes I may forget). &lt;br /&gt;
&lt;br /&gt;
This next example demonstrates changing a property value for the current selections. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
if fnWhichComponent(thisComponent) = &amp;quot;Text&amp;quot; then&lt;br /&gt;
   oCurSelection = thisComponent.getCurrentSelection()&lt;br /&gt;
   if oCurSelection.supportsService(&amp;quot;com.sun.star.text.TextRanges&amp;quot;) then&lt;br /&gt;
      nCount = oCurSelection.Count&lt;br /&gt;
      &amp;#039;xray.xray oCurSelection.getByIndex(0)&lt;br /&gt;
      &amp;#039;Warning: The insertion point will have the same action applied twice&lt;br /&gt;
      &amp;#039;in this case it doesn&amp;#039;t matter, but in others it might.&lt;br /&gt;
      for i = 0 to nCount - 1&lt;br /&gt;
         oCurSelection.getByIndex(i).setPropertyValue(&amp;quot;CharStyleName&amp;quot;, &amp;quot;Strong Emphasis&amp;quot;)&lt;br /&gt;
      next&lt;br /&gt;
   end if&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
In OpenOffice.org Basic it is possible to shorten the assignment line to: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oCurSelection(i).CharStyleName = &amp;quot;Strong Emphasis&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This wiki will try to use the full methods for both indexing and assigning properties. The rationale is that this makes converting the code to other languages easier and also helps the learner to understand what is happening (again I have not been in the habit of doing this so some examples may slip past me). &lt;br /&gt;
&lt;br /&gt;
Exercise 2: Rewrite the above code so that the warning can be removed. &lt;br /&gt;
&lt;br /&gt;
See [[ Current selection]]. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Iterative Access to Subordinate Objects (Enumeration access)=&lt;br /&gt;
Sometimes to access the desired object an enumeration is required. For example paragraphs, within a document or within a selection. &lt;br /&gt;
&lt;br /&gt;
When a Writer document is active and some text is selected, both &amp;lt;tt&amp;gt;thisDocument.getText()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;thisComponent.getCurrentSelection().getByIndex(i)&amp;lt;/tt&amp;gt; have the service: com.sun.star.text.TextRange which has the interface: com.sun.star.container.XContentEnumerationAccess, it is possible to create an enumeration of the paragraphs for the current document or for a particular selection. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; Create enumeration object&lt;br /&gt;
oTextElementEnum = thisComponent.getText().createEnumeration()&lt;br /&gt;
&amp;#039;or thisComponent.getCurrentSelection().getByIndex(i).createEnumeration()&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; loop over all text elements&lt;br /&gt;
while oTextElementEnum.hasMoreElements()&lt;br /&gt;
        oTextElement = oTextElementEnum.nextElement&lt;br /&gt;
        if oTextElement.supportsService(&amp;quot;com.sun.star.text.TextTable&amp;quot;) then&lt;br /&gt;
                MsgBox &amp;quot;The current block contains a table.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
        if oTextElement.supportsService(&amp;quot;com.sun.star.text.Paragraph&amp;quot;) then&lt;br /&gt;
                MsgBox &amp;quot;The current block contains a paragraph.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
wend&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Exercise 3: Extend the above example to display in a message box all text portions that are bold. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Named access=&lt;br /&gt;
Some objects provide named access to a particular type of subordinate object, some others indexed access, and some both named and indexed access. &lt;br /&gt;
&lt;br /&gt;
For example if the current document in OpenOffice.org is a spreadsheet then to access a particular sheet can be done by index access: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oSheet = thisComponent.getSheets.getByIndex(0)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
or named access: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oSheet = thisComponent.getSheets.getByName(&amp;quot;Sheet1&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To check if an object with a particular name already exists use &amp;lt;tt&amp;gt;hasByName&amp;lt;/tt&amp;gt;, for example: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
if thisComponent.getSheets.hasByName(&amp;quot;Sheet1&amp;quot;) then&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To loop through all the available object names can be done like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
mNames = thisComponent.getSheets.getElementnames&lt;br /&gt;
for i = lbound(mNames) to ubound(mNames)&lt;br /&gt;
        msgbox mNames(i)&lt;br /&gt;
next&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Some named subordinate objects also provide the interface:  com.sun.star.container.XNameContainer. This interface defines that such objects should have the following methods: &amp;lt;tt&amp;gt;insertByName&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;replaceByname&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;removeByName&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
E.g. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
thisComponent.getSheets.insertByName(&amp;quot;NewSheet&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Create new objects=&lt;br /&gt;
Some objects have services which implement interfaces to provide specific methods for creating a particular type of object. &lt;br /&gt;
&lt;br /&gt;
For example if the current document is a Writer document then &amp;lt;tt&amp;gt;thisComponent.getText&amp;lt;/tt&amp;gt; is an object that provides the service com.sun.star.text.Text which implements the interface  com.sun.star.text.XSimpleText which defines the methods &amp;lt;tt&amp;gt;createTextCursor&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;createTextCursorByRange&amp;lt;/tt&amp;gt;. Both of these methods create a text cursor for accessing the text of the document. These cursors are quite independent of the view cursor . The view cursor is visible on the screen and is manipulated by the user (and can be manipulated by program control), where as a text cursor is not visible on the screen and is solely used by program control. The following code snippet demonstrates creating a new text cursor, such that it starts at the same location as the viewCursor and is then moved independent of the view cursor. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oVC = thisComponent.getCurrentController.getViewCursor&lt;br /&gt;
oCursor = oVC.getText.createTextCursorByRange(oVC)&lt;br /&gt;
oCursor.gotoStartOfSentence(false)&lt;br /&gt;
oCursor.gotoEndOfSentence(true)&lt;br /&gt;
msgbox oCursor.getString&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Some objects are context dependent and get created using the method &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt; which is defined in the interface com.sun.star.lang.XMultiServiceFactory. For example to add a rectangle to the first page of a drawing document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
dim aPoint as new com.sun.star.awt.Point&lt;br /&gt;
dim aSize as new com.sun.star.awt.Size&lt;br /&gt;
 &lt;br /&gt;
aPoint.x = 1000&lt;br /&gt;
aPoint.y = 1000&lt;br /&gt;
 &lt;br /&gt;
aSize.Width = 10000&lt;br /&gt;
aSize.Height = 10000&lt;br /&gt;
 &lt;br /&gt;
oRectangleShape = thisComponent.createInstance(&amp;quot;com.sun.star.drawing.RectangleShape&amp;quot;)&lt;br /&gt;
oRectangleShape.Size = aSize&lt;br /&gt;
oRectangleShape.Position = aPoint&lt;br /&gt;
 &lt;br /&gt;
thisComponent.getDrawPages.getByIndex(0).add(oRectangleShape)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example also uses UNO structs see below for more information on UNO stucts. &lt;br /&gt;
&lt;br /&gt;
Some objects are context independent to create these objects use the OpenOffice.org Basic command createUnoService. For example to create the equivalent to StarDesktop: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDesktop = createUnoService(&amp;quot;com.sun.star.frame.Desktop&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The process that I use to determine how to access or create an object is as follows: &lt;br /&gt;
&lt;br /&gt;
Does the object already exist if so I should be able to access it from something like &amp;lt;tt&amp;gt;thisComponent&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Will the new object belong to another object, if so does the owner have a specific method for creating the object, if so use it. &lt;br /&gt;
&lt;br /&gt;
The new object will belong to another object, but that object doesn&amp;#039;t provide a specific method for creating it, but does provide &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt;. If the object doesn&amp;#039;t provide &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt; are you sure you are using the correct object, or is it context independent. &lt;br /&gt;
&lt;br /&gt;
I have found working out how to create an object to be quite difficult with existing documentation so I hope that this document/wiki will eventually make this clear. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==UNO structs==&lt;br /&gt;
UNO structures can be declared using the OpenOffice.org Basic command &amp;lt;tt&amp;gt;dim&amp;lt;/tt&amp;gt;: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
dim aPoint as new com.sun.star.awt.Point&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Or by using the OpenOffice.org Basic command &amp;lt;tt&amp;gt;createUnoStruct&amp;lt;/tt&amp;gt;: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
aPoint = createUnoStruct(&amp;quot;com.sun.star.awt.Point&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|When declaring UNO structs case is important. Note that everything upto the name of the struct is lowercase, and that the name of the struct is in TitleCase.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Creating Listeners and Handlers==&lt;br /&gt;
Through the user interface it is possible to assign macros to some events: &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org versions 1.1.x: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Configure… &amp;gt; Events&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org versions 1.9.x and above: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Customize… &amp;gt; Events&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
It is also possible to assign macros to a wider range of events using the OpenOffice.org Basic command CreateUnoListener. This same command is used for creating both listeners and handlers. A listener checks for an event and always allows other listeners to respond to the event as well. A handler listens for an event, and can optionally consume the event so that other listeners don&amp;#039;t get to act on it. &lt;br /&gt;
&lt;br /&gt;
The following example creates a keyHandler: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
global IannzExampleKeyHandler&lt;br /&gt;
 &lt;br /&gt;
sub SetupKeyHandler&lt;br /&gt;
oController = thisComponent.currentController&lt;br /&gt;
IannzExampleKeyHandler = CreateUnoListener(&amp;quot;KeyHandler_&amp;quot;,&amp;quot;com.sun.star.awt.XKeyHandler&amp;quot;)&lt;br /&gt;
oController.addKeyHandler(IannzExampleKeyHandler) &amp;#039; Register the listener&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
sub RemoveKeyHandler&lt;br /&gt;
thisComponent.currentController.removeKeyHandler(IannzExampleKeyHandler)&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
sub KeyHandler_disposing&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function KeyHandler_keyReleased(oKeyEvent as new com.sun.star.awt.KeyHandler) as boolean&lt;br /&gt;
        KeyHandler_keyReleased = False    &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function KeyHandler_keyPressed(oKeyEvent as new com.sun.star.awt.KeyHandler) as boolean&lt;br /&gt;
KeyHandler_keyPressed = false   &amp;#039;Let other listeners handle the event&lt;br /&gt;
if oKeyEvent.modifiers = com.sun.star.awt.KeyModifier.MOD2 then &amp;#039;Control key was pressed&lt;br /&gt;
        if oKeyEvent.keyCode = com.sun.star.awt.Key.Q then&lt;br /&gt;
                msgbox &amp;quot;Alt + Q was pressed&amp;quot;&lt;br /&gt;
                KeyHandler_keyPressed = true    &amp;#039;Don&amp;#039;t let other listeners process this event&lt;br /&gt;
        end if&lt;br /&gt;
end if&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
A variable declared as global keeps its value even after the macro exits. In this case we want to be able to use this variable later to remove the handler. As variables declared globally could be used in other libraries to try and avoid conflict I start all my global variables with Iannz my registered name for the OpenOffice.org web site. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;sub SetupKeyHandler&amp;lt;/tt&amp;gt; sets up the handler. The first parameter to CreateUnoListener is the staring name for the methods that will be called when that type of event occurs in this example .&amp;lt;tt&amp;gt;&amp;quot;KeyHandler_&amp;quot;&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
The second parameter is the name of the interface for the listener or handler, &amp;quot;com.sun.star.awt.XKeyHandler&amp;quot;. The name is case sensitive, everything up to and including the module name is always lowercase, the name of the interface always starts with &amp;quot;X&amp;quot; and the remainder is in TitleCase. &lt;br /&gt;
&lt;br /&gt;
Use the SDK to find out what methods the interface must supply. You must supply routines for all of these methods even if you don&amp;#039;t intend to use them. You also need to supply a disposing method. The names of these routines start with the string given in the first parameter to CreateUnoListener , in this example &amp;lt;tt&amp;gt;&amp;quot;KeyHandler_&amp;quot;&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Thus in the example there is &amp;lt;tt&amp;gt;KeyHandler_disposing&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;KeyHandler_keyReleased&amp;lt;/tt&amp;gt; which don&amp;#039;t actually do anything but are required, and &amp;lt;tt&amp;gt;KeyHandler_keyPressed&amp;lt;/tt&amp;gt; which actually does the job. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;sub RemoveKeyHandler&amp;lt;/tt&amp;gt; demonstrates how to remove the handler.&lt;br /&gt;
&lt;br /&gt;
=OpenOffice.org constants=&lt;br /&gt;
The above example uses OpenOffice.org constants. &lt;br /&gt;
&lt;br /&gt;
E.g. com.sun.star.awt.KeyModifier.MOD2&lt;br /&gt;
&lt;br /&gt;
OpenOffice.org constants are case sensitive. Everything up to and including the module name is always lowercase. The constant group is in TitleCase. The actual constant name is always UPPERCASE. &lt;br /&gt;
&lt;br /&gt;
Programmers not using OpenOffice.org Basic may not have access to these constants. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Using the recorder=&lt;br /&gt;
See [[ The OpenOffice.org recorder and UNO dispatch calls]] section for a discussion on recording UNO Dispatch commands versus writing API calls.&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=L%27enregistreur_de_macro_OpenOffice.org_et_les_appels_UNO_(dispatch)&amp;diff=7475</id>
		<title>L&#039;enregistreur de macro OpenOffice.org et les appels UNO (dispatch)</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=L%27enregistreur_de_macro_OpenOffice.org_et_les_appels_UNO_(dispatch)&amp;diff=7475"/>
		<updated>2006-04-04T06:22:39Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;The OpenOffice.org recorder and UNO dispatch calls&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org provides a recorder, to record a series of actions, in &amp;#039;&amp;#039;&amp;#039;Writer and Calc only&amp;#039;&amp;#039;&amp;#039;, to produce some code. The recorder produces a series of UNO dispatch calls, which are not particularly useful for learning the OpenOffice.org API model. I personally find the code that the recorder produces to be a little hard to follow. It is generally considered preferable to use OpenOffice.org API calls but sometimes the only way or most convenient way is to use UNO dispatch calls.&lt;br /&gt;
&lt;br /&gt;
For a list of dispatch calls see: http://www.openoffice.org/files/documents/25/2570/commandsReference.html&lt;br /&gt;
&lt;br /&gt;
Below are three versions of the same macro: &lt;br /&gt;
&lt;br /&gt;
*Recorded example&lt;br /&gt;
*Tidied UNO dispatch calls&lt;br /&gt;
*API Calls&lt;br /&gt;
&lt;br /&gt;
The series of steps recorded were: &lt;br /&gt;
&lt;br /&gt;
Type &amp;quot;Some text&amp;quot; ; Press &amp;#039;&amp;#039;&amp;#039;Enter&amp;#039;&amp;#039;&amp;#039;; Type &amp;quot;A new paragraph with a &amp;quot;; &amp;#039;&amp;#039;&amp;#039;Format &amp;gt; Character… &amp;gt; Bold &amp;gt; OK&amp;#039;&amp;#039;&amp;#039;; Type &amp;quot;bold&amp;quot;; &amp;#039;&amp;#039;&amp;#039;Format &amp;gt; Character… &amp;gt; Regular&amp;gt; OK&amp;#039;&amp;#039;&amp;#039;; Type &amp;quot; word in it&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|This would be best handled with autotext, but this simple example demonstrates the point.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Recorded example==&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub Example&lt;br /&gt;
rem ----------------------------------------------------------------------&lt;br /&gt;
rem define variables&lt;br /&gt;
dim document   as object&lt;br /&gt;
dim dispatcher as object&lt;br /&gt;
rem ----------------------------------------------------------------------&lt;br /&gt;
rem get access to the document&lt;br /&gt;
document   = ThisComponent.CurrentController.Frame&lt;br /&gt;
dispatcher = createUnoService(&amp;quot;com.sun.star.frame.DispatchHelper&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
rem ----------------------------------------------------------------------&lt;br /&gt;
dim args1(0) as new com.sun.star.beans.PropertyValue&lt;br /&gt;
args1(0).Name = &amp;quot;Text&amp;quot;&lt;br /&gt;
args1(0).Value = &amp;quot;Some text&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
dispatcher.executeDispatch(document, &amp;quot;.uno:InsertText&amp;quot;, &amp;quot;&amp;quot;, 0, args1())&lt;br /&gt;
 &lt;br /&gt;
rem ----------------------------------------------------------------------&lt;br /&gt;
dispatcher.executeDispatch(document, &amp;quot;.uno:InsertPara&amp;quot;, &amp;quot;&amp;quot;, 0, Array())&lt;br /&gt;
 &lt;br /&gt;
rem ----------------------------------------------------------------------&lt;br /&gt;
dim args3(0) as new com.sun.star.beans.PropertyValue&lt;br /&gt;
args3(0).Name = &amp;quot;Text&amp;quot;&lt;br /&gt;
args3(0).Value = &amp;quot;A new paragraph with a &amp;quot;&lt;br /&gt;
 &lt;br /&gt;
dispatcher.executeDispatch(document, &amp;quot;.uno:InsertText&amp;quot;, &amp;quot;&amp;quot;, 0, args3())&lt;br /&gt;
 &lt;br /&gt;
rem ----------------------------------------------------------------------&lt;br /&gt;
dim args4(0) as new com.sun.star.beans.PropertyValue&lt;br /&gt;
args4(0).Name = &amp;quot;Bold&amp;quot;&lt;br /&gt;
args4(0).Value = true&lt;br /&gt;
 &lt;br /&gt;
dispatcher.executeDispatch(document, &amp;quot;.uno:Bold&amp;quot;, &amp;quot;&amp;quot;, 0, args4())&lt;br /&gt;
 &lt;br /&gt;
rem ----------------------------------------------------------------------&lt;br /&gt;
dim args5(0) as new com.sun.star.beans.PropertyValue&lt;br /&gt;
args5(0).Name = &amp;quot;Text&amp;quot;&lt;br /&gt;
args5(0).Value = &amp;quot;bold&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
dispatcher.executeDispatch(document, &amp;quot;.uno:InsertText&amp;quot;, &amp;quot;&amp;quot;, 0, args5())&lt;br /&gt;
 &lt;br /&gt;
rem ----------------------------------------------------------------------&lt;br /&gt;
dim args6(0) as new com.sun.star.beans.PropertyValue&lt;br /&gt;
args6(0).Name = &amp;quot;Bold&amp;quot;&lt;br /&gt;
args6(0).Value = false&lt;br /&gt;
 &lt;br /&gt;
dispatcher.executeDispatch(document, &amp;quot;.uno:Bold&amp;quot;, &amp;quot;&amp;quot;, 0, args6())&lt;br /&gt;
 &lt;br /&gt;
rem ----------------------------------------------------------------------&lt;br /&gt;
dim args7(0) as new com.sun.star.beans.PropertyValue&lt;br /&gt;
args7(0).Name = &amp;quot;Text&amp;quot;&lt;br /&gt;
args7(0).Value = &amp;quot; word in it.&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
dispatcher.executeDispatch(document, &amp;quot;.uno:InsertText&amp;quot;, &amp;quot;&amp;quot;, 0, args7())&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Tidied UNO dispatch calls==&lt;br /&gt;
(This heading is linked to from [[ UNO Dispatch]], so if you change it change the link as well.) &lt;br /&gt;
&lt;br /&gt;
Now the same example having been tidied using a function for calling the UNO dispatch calls (some UNO Dispatch calls return a value so using a function makes it more generically useful than a sub): &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub Example&lt;br /&gt;
fnDispatch(&amp;quot;InsertText&amp;quot;, array(&amp;quot;Text&amp;quot;,&amp;quot;Some text&amp;quot;))&lt;br /&gt;
fnDispatch(&amp;quot;InsertPara&amp;quot;)&lt;br /&gt;
fnDispatch(&amp;quot;InsertText&amp;quot;, array(&amp;quot;Text&amp;quot;,&amp;quot;A new paragraph with a &amp;quot;))&lt;br /&gt;
fnDispatch(&amp;quot;Bold&amp;quot;, array(&amp;quot;Bold&amp;quot;,true))&lt;br /&gt;
fnDispatch(&amp;quot;InsertText&amp;quot;, array(&amp;quot;Text&amp;quot;,&amp;quot;bold&amp;quot;))&lt;br /&gt;
fnDispatch(&amp;quot;Bold&amp;quot;, array(&amp;quot;Bold&amp;quot;,false))&lt;br /&gt;
fnDispatch(&amp;quot;InsertText&amp;quot;, array(&amp;quot;Text&amp;quot;,&amp;quot; word in it.&amp;quot;))&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function fnDispatch(sCommand as string, optional mArgs)&lt;br /&gt;
oFrame = ThisComponent.getCurrentController.getFrame&lt;br /&gt;
oDispatcher = createUnoService(&amp;quot;com.sun.star.frame.DispatchHelper&amp;quot;)&lt;br /&gt;
&amp;#039;on error resume next&lt;br /&gt;
if isMissing(mArgs) then&lt;br /&gt;
        fnDispatch = oDispatcher.executeDispatch(oFrame, &amp;quot;.uno:&amp;quot; &amp;amp; sCommand, &amp;quot;&amp;quot;, 0, array())&lt;br /&gt;
else&lt;br /&gt;
        nArgs = uBound(mArgs) \ 2&lt;br /&gt;
        dim Args(nArgs) as new com.sun.star.beans.PropertyValue&lt;br /&gt;
        for i = 0 to nArgs&lt;br /&gt;
                Args(i).name = mArgs(i * 2)&lt;br /&gt;
                Args(i).value = mArgs(i * 2 + 1)&lt;br /&gt;
        next&lt;br /&gt;
        fnDispatch = oDispatcher.executeDispatch(oFrame, &amp;quot;.uno:&amp;quot; &amp;amp; sCommand, &amp;quot;&amp;quot;, 0, Args())&lt;br /&gt;
end if&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==API calls==&lt;br /&gt;
Finally the same example using API calls: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub Example&lt;br /&gt;
oVC = thisComponent.getCurrentController.getViewCursor&lt;br /&gt;
oText = oVC.text&lt;br /&gt;
oText.insertString(oVC, &amp;quot;Some text&amp;quot;, False)&lt;br /&gt;
oText.insertControlCharacter(oVC, com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK, False)&lt;br /&gt;
oText.insertString(oVC, &amp;quot;A new paragraph with a &amp;quot;, False)&lt;br /&gt;
oVC.setPropertyValue(&amp;quot;CharWeight&amp;quot;, com.sun.star.awt.FontWeight.BOLD)&lt;br /&gt;
oText.insertString(oVC, &amp;quot;bold&amp;quot;, false)&lt;br /&gt;
oVC.setPropertyValue(&amp;quot;CharWeight&amp;quot;, com.sun.star.awt.FontWeight.NORMAL)&lt;br /&gt;
oText.insertString(oVC, &amp;quot; word in it.&amp;quot;, false)&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Current_selection&amp;diff=7472</id>
		<title>Current selection</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Current_selection&amp;diff=7472"/>
		<updated>2006-04-04T06:11:19Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;Current Selection in Text Documents&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Also see [[ Getting started]]. &lt;br /&gt;
&lt;br /&gt;
Having made sure that text is selected, it is common to create a loop to do something to all of the currently selected text. But, remember that the first element of the array is either the current selection when there is only one selection, or the insertion point when there is more than one selection. Thus the following common code: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oCurSelection = thisComponent.getCurrentSelection()&lt;br /&gt;
if oCurSelection.supportsService(&amp;quot;com.sun.star.text.TextRanges&amp;quot;) then&lt;br /&gt;
   nCount = oCurSelection.Count&lt;br /&gt;
   if nCount = 1 then&lt;br /&gt;
      oTextRange = oCurSelection.getByIndex(0)&lt;br /&gt;
      &amp;#039;Do some action on oTextRange&lt;br /&gt;
   else&lt;br /&gt;
      for i = 1 to nCount - 1&lt;br /&gt;
         oTextRange = oCurSelection.getByIndex(i)&lt;br /&gt;
         &amp;#039;Do some action on oTextRange&lt;br /&gt;
      next&lt;br /&gt;
   end if&lt;br /&gt;
end if&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=URL_Basics&amp;diff=7471</id>
		<title>URL Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=URL_Basics&amp;diff=7471"/>
		<updated>2006-04-04T06:08:15Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The following information is based on material found in: &amp;lt;br&amp;gt; StarOffice™ 7 Office Suite &amp;lt;br&amp;gt; A Sun™ ONE Software Offering &amp;lt;br&amp;gt; Basic Programmer&amp;#039;s Guide &amp;lt;br&amp;gt; Page 74. See http://docs.sun.com/app/docs/doc/817-1826?q=StarOffice. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=File Names in URL Notation=&lt;br /&gt;
Since OpenOffice.org is a platform-independent application, it uses URL notation (which is independent of any operating system), as defined in the Internet Standard RFC 1738 for file names. Standard file names using this system begin with the prefix file:/// followed by the local path. If the file name contains sub-directories, then these are separated by a single forward slash., not with a backslash usually used under Windows. The following path references the test.sxw file in the doc directory on the C drive:. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
file:///C:/doc/test.sxw&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To covert local file names into an URL, OpenOffice.org provides the ConvertToUrl function. To convert an URL into a local file name, OpenOffice.org provides the ConvertFromUrl function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
MsgBox ConvertToUrl(&amp;quot;C:\doc\test.sxw&amp;quot;) &amp;#039; supplies file:///C:/doc/test.sxw&lt;br /&gt;
MsgBox ConvertFromUrl(&amp;quot;file:///C:/doc/test.sxw&amp;quot;) &amp;#039; supplies (under Windows) c:\doc\test.sxw&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The example converts a local file name into a URL and displays it in a message box. It then converts a URL into a local file name and also displays this. &lt;br /&gt;
&lt;br /&gt;
The Internet Standard RFC 1738, upon which this is based, permits use of the 0-9, a-z, and A-Z characters. All other characters are inserted as escape coding in the URLs. To do this, they are converted into their hexadecimal value in the ISO 8859-1 (ISO-Latin) set of characters and are preceded by a percent sign. A space in a local file name therefore, for example, becomes a %20 in the URL.&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=URL_Basics&amp;diff=7470</id>
		<title>URL Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=URL_Basics&amp;diff=7470"/>
		<updated>2006-04-04T06:07:09Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The following information is based on material found in: &amp;lt;br&amp;gt; StarOffice™ 7 Office Suite &amp;lt;br&amp;gt; A Sun™ ONE Software Offering &amp;lt;br&amp;gt; Basic Programmer&amp;#039;s Guide &amp;lt;br&amp;gt; Page 74. See http://docs.sun.com/app/docs/doc/817-1826?q=StarOffice. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=File Names in URL Notation=&lt;br /&gt;
Since OpenOffice.org is a platform-independent application, it uses URL notation (which is independent of any operating system), as defined in the Internet Standard RFC 1738 for file names. Standard file names using this system begin with the prefix file:/// followed by the local path. If the file name contains sub-directories, then these are separated by a single forward slash., not with a backslash usually used under Windows. The following path references the test.sxw file in the doc directory on the C drive:. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
file:///C:/doc/test.sxw&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To covert local file names into an URL, OpenOffice.org provides the [[ ConvertToUrl]] function. To convert an URL into a local file name, OpenOffice.org provides the [[ ConvertFromUrl]] function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
MsgBox ConvertToUrl(&amp;quot;C:\doc\test.sxw&amp;quot;) &amp;#039; supplies file:///C:/doc/test.sxw&lt;br /&gt;
MsgBox ConvertFromUrl(&amp;quot;file:///C:/doc/test.sxw&amp;quot;) &amp;#039; supplies (under Windows) c:\doc\test.sxw&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The example converts a local file name into a URL and displays it in a message box. It then converts a URL into a local file name and also displays this. &lt;br /&gt;
&lt;br /&gt;
The Internet Standard RFC 1738, upon which this is based, permits use of the 0-9, a-z, and A-Z characters. All other characters are inserted as escape coding in the URLs. To do this, they are converted into their hexadecimal value in the ISO 8859-1 (ISO-Latin) set of characters and are preceded by a percent sign. A space in a local file name therefore, for example, becomes a %20 in the URL.&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Extensions_development_basic&amp;diff=7469</id>
		<title>Extensions development basic</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Extensions_development_basic&amp;diff=7469"/>
		<updated>2006-04-04T06:02:11Z</updated>

		<summary type="html">&lt;p&gt;Iannz: /* Creating new documents */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;Getting started tutorial&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
This page provides a getting started guide for writing macros in OpenOffice.org Basic. It assumes some prior programming knowledge. Please edit this page to make it more readable. I hope you will find it useful in getting started.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Where do I write the code?=&lt;br /&gt;
OpenOffice.org Basic code is stored in modules within libraries. A library can be: &lt;br /&gt;
&lt;br /&gt;
*Shared (for a network install - OOo Macros &amp;amp; Dialogs) &lt;br /&gt;
*Just for the current user (My Macros &amp;amp; Dialogs) &lt;br /&gt;
*Within a document or template, so that its code is only available when that document is open.Within a document or template, so that its code is only available when that document is open. &lt;br /&gt;
Libraries not stored in a document or template (that is libraries that are shared or for the current user) are referred to as &amp;#039;&amp;#039;&amp;#039;OpenOffice.org libraries&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
To determine the actual folders that contain the OpenOffice.org libraries see:&amp;lt;br&amp;gt; &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Options… &amp;gt; OpenOffice.org &amp;gt; Paths &amp;gt; BASIC&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|Do not copy or move libraries using operating system commands. Use the macro organizer or package manager instead.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Modules within libraries have a maximum size of 64kb. A library can contain up to 16,000 modules. &lt;br /&gt;
&lt;br /&gt;
For more information see online help for: Modules and Libraries. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Accessing the IDE=&lt;br /&gt;
To access the IDE for the first time: &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org 1.1.x: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Macro… &amp;gt;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org 1.9.x and above: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Organize macros &amp;gt; OpenOffice.org Basic… &amp;gt;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
To get started we will use Module1 in the Standard library which is stored for the current user only: &lt;br /&gt;
&lt;br /&gt;
Type a name for the new macro: &amp;#039;&amp;#039;&amp;#039;HelloWorld&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
In the macro from listbox select &amp;#039;&amp;#039;&amp;#039;Standard&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Click &amp;#039;&amp;#039;&amp;#039;New&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
You should now see something like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
REM  *****  BASIC  *****&lt;br /&gt;
 &lt;br /&gt;
Sub Main&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
 &lt;br /&gt;
Sub HelloWorld&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The cursor will be positioned at the start of the &amp;lt;tt&amp;gt;Sub HelloWorld&amp;lt;/tt&amp;gt; line. &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|Now that while the IDE is running it can be accessed from the OpenOffice.org Window menu, or the task panel provided by the operating system.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Entering the code=&lt;br /&gt;
Select and delete: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
REM  *****  BASIC  *****&lt;br /&gt;
 &lt;br /&gt;
Sub Main&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Below the line &amp;quot;Sub HelloWorld&amp;quot; type &amp;lt;tt&amp;gt;msgbox &amp;quot;Hello World!&amp;quot;&amp;lt;/tt&amp;gt;, so that the editor looks like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Sub HelloWorld&lt;br /&gt;
msgbox &amp;quot;Hello World!&amp;quot;&lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Notes:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|The IDE does not provide code completion or help with command syntax as you type, but to get help on a Basic command position the cursor in the command and press F1.&amp;lt;br&amp;gt; OpenOffice.org Basic commands are not case sensitive. Thus msgbox, MSGBOX and Msgbox will all work.&amp;lt;br&amp;gt; Strings are enclosed in double quotes.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Running the code=&lt;br /&gt;
There are several ways of running the Basic code, these include: &lt;br /&gt;
&lt;br /&gt;
Directly from the IDE. There is a run button on the macro bar (by default the third control on the second toolbar). This will run the first macro in the current module. &lt;br /&gt;
&lt;br /&gt;
From the tools menu: (Version 1.1.x) &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Macro…&amp;#039;&amp;#039;&amp;#039;; (Version 1.9.x and above) &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macro &amp;gt; Run Macro…&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a [[ key press]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a [[ menu entry]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a toolbar button. &lt;br /&gt;
&lt;br /&gt;
Creating a [[ control in a document]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to an event. &lt;br /&gt;
&lt;br /&gt;
For now try running the &amp;quot;HelloWorld&amp;quot; subroutine by clicking the &amp;#039;&amp;#039;&amp;#039;Run&amp;#039;&amp;#039;&amp;#039; button. A small dialog titled &amp;quot;soffice&amp;quot; with the text &amp;quot;Hello World!&amp;quot; and an OK button should be displayed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Saving the code=&lt;br /&gt;
The code gets automatically saved whenever the container for the code gets saved. Thus, if the code is in an OpenOffice.org library (shared or users) then it gets automatically saved when OpenOffice.org exits. If the code is in a library which is part of a document it gets saved whenever the document is saved. &lt;br /&gt;
&lt;br /&gt;
On the Standard toolbar (by default the top toolbar) in the IDE there is a save button. If the code is in a document or template then clicking this button saves the entire document or template. If the code is in an OpenOffice.org library then just the current library gets saved. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Variables=&lt;br /&gt;
It is possible to force variable declaration with &amp;lt;tt&amp;gt;Option Explicit&amp;lt;/tt&amp;gt; at the top of the module. For a discussion on whether to declare variables or not see: [[http://www.oooforum.org/forum/viewtopic.phtml?t=5845 this discussion]]. &lt;br /&gt;
&lt;br /&gt;
In that discussion the initial author of this wiki thought that variables should always be declared. Since then he has changed to not declaring them. In short it is generally a personal preference. In either case, it is the initial authors preference that variables be named according to the following convention, which is used in the examples in this Wiki: &lt;br /&gt;
&lt;br /&gt;
The first letter of the variable name indicates the type of value that the variable is going to hold, as per the following table (based on a table in Tutorial.pdf by Sun) &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Letter&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Meaning&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|-&lt;br /&gt;
|a&lt;br /&gt;
|Structure&lt;br /&gt;
|-&lt;br /&gt;
|b&lt;br /&gt;
|Boolean (TRUE or FALSE)&lt;br /&gt;
|-&lt;br /&gt;
|e&lt;br /&gt;
|Enumeration. This variable can only have one of a limited set of values.&lt;br /&gt;
|-&lt;br /&gt;
|f&lt;br /&gt;
|Float (3.402823 x 1038 to 1.401298 x 10-45. A single variable can take up to four bytes)&amp;lt;br&amp;gt; Double (1.79769313486232 x 10308 to 4.94065645841247 x 10-324. A double variable can take up to eight bytes)&amp;lt;br&amp;gt; Currency (-922337203685477.5808 to +922337203685477.5807 and takes up to eight bytes of memory)&lt;br /&gt;
|-&lt;br /&gt;
|m&lt;br /&gt;
|Array (aka sequence aka matrix)&lt;br /&gt;
|-&lt;br /&gt;
|n&lt;br /&gt;
|Integer (-32768 to 32767.) or&amp;lt;br&amp;gt; Long (-2147483648 and 2147483647).&lt;br /&gt;
|-&lt;br /&gt;
|o&lt;br /&gt;
|Object, service, or interface&lt;br /&gt;
|-&lt;br /&gt;
|s&lt;br /&gt;
|String (A string variable can store up to 65535 Unicode characters).&lt;br /&gt;
|-&lt;br /&gt;
|x&lt;br /&gt;
|Interface, to indicate that only operations of a particular interface of an object are used&lt;br /&gt;
|-&lt;br /&gt;
|v&lt;br /&gt;
|Variant, Any&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Use long descriptive variable names making use of camel case &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|User defined OpenOffice.org Basic variables are not case sensitive. But UNO-API constants are case sensitive.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Convention exceptions to long descriptive names is for index variables where i, j, and k are commonly used, and for when a string is being built-up, where s is commonly used. &lt;br /&gt;
&lt;br /&gt;
Edit sub HelloWorld so that it looks like the following and run it: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub HelloWorld&lt;br /&gt;
dim i as integer &amp;#039;This line is optional&lt;br /&gt;
for i = 0 to 2&lt;br /&gt;
        &amp;#039;These lines are indented for ease of reading only&lt;br /&gt;
        msgbox &amp;quot;Hello World &amp;quot; &amp;amp; i&lt;br /&gt;
next&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
For more information on variables see the online help for &amp;quot;using variables&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=Understanding the OpenOffice.org API=&lt;br /&gt;
This section will start with an example. The remainder of this section aims to give information so that the example can be understood and expanded upon. &lt;br /&gt;
&lt;br /&gt;
Try running the following code with different types of documents being active. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
&amp;#039;basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
&amp;#039;xray.xray thisComponent&lt;br /&gt;
msgbox fnWhichComponent(thisComponent)&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function fnWhichComponent(oDoc) as string&lt;br /&gt;
if HasUnoInterfaces(oDoc, &amp;quot;com.sun.star.lang.XServiceInfo&amp;quot;) then &lt;br /&gt;
   if thisComponent.supportsService (&amp;quot;com.sun.star.text.GenericTextDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Text&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.sheet.SpreadsheetDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Spreadsheet&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.presentation.PresentationDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Presentation&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.drawing.GenericDrawingDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Drawing&amp;quot;&lt;br /&gt;
   else&lt;br /&gt;
      fnWhichComponent = &amp;quot;Oops current document something else&amp;quot;&lt;br /&gt;
   end if&lt;br /&gt;
else&lt;br /&gt;
   fnWhichComponent = &amp;quot;Not a document&amp;quot;&lt;br /&gt;
end if&lt;br /&gt;
End function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subroutine naming convention==&lt;br /&gt;
In the above example the user defined function has a name that starts with the letters &amp;quot;fn&amp;quot;. This is the initial authors convention so that people know that this is a user defined function. Similarly, the initial author uses the convention that user defined subroutines start with the letters &amp;quot;sub&amp;quot;. When learning a language and an API it can be difficult to know what is built-in and what has been defined elsewhere. This document/wiki will use this convention for naming functions and subroutines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Introducing the OpenOffice.org API==&lt;br /&gt;
This section introduces the following terms: &lt;br /&gt;
&lt;br /&gt;
* Interface &lt;br /&gt;
* Module &lt;br /&gt;
* Service &lt;br /&gt;
* Method &lt;br /&gt;
* Property &lt;br /&gt;
&lt;br /&gt;
Understanding the difference between an interface and a service and what a module is, is not essential to being able to write extensions for OpenOffice.org, but it does help interpreting the documentation, and for introspection purposes. You may need to read this section at least twice. &lt;br /&gt;
&lt;br /&gt;
An &amp;#039;&amp;#039;&amp;#039;interface&amp;#039;&amp;#039;&amp;#039; is a &amp;#039;&amp;#039;definition&amp;#039;&amp;#039; of a set of methods (and their arguments) that a service which implements that interface must have. &lt;br /&gt;
&lt;br /&gt;
Interfaces are grouped together in &amp;#039;&amp;#039;&amp;#039;modules&amp;#039;&amp;#039;&amp;#039; for naming purposes. All interfaces (and services) start with the name &amp;quot;com.sun.star&amp;quot; then the name of the module then the name of the interface (or service). &lt;br /&gt;
&lt;br /&gt;
For example most services provide the com.sun.star.beans.XPropertySet interface. This interface is stored in the module &amp;quot;beans&amp;quot; and provides access to the properties of a service. A &amp;#039;&amp;#039;&amp;#039;property&amp;#039;&amp;#039;&amp;#039; is a value where as a &amp;#039;&amp;#039;&amp;#039;method&amp;#039;&amp;#039;&amp;#039; is an action. &lt;br /&gt;
&lt;br /&gt;
An OpenOffice.org object can have many services. &lt;br /&gt;
&lt;br /&gt;
An OpenOffice.org object may have a service, which implements an interface, in which a method description says that another OpenOffice.org object is returned.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Introspection==&lt;br /&gt;
HasUnoInterfaces is an OpenOffice.org Basic function for introspection. See this [[http://www.oooforum.org/forum/viewtopic.phtml?t=7068 link]] for information on introspection in other languages. &lt;br /&gt;
&lt;br /&gt;
HasUnoInterfaces returns true if all of the specified interfaces are available for the specified object. &lt;br /&gt;
&lt;br /&gt;
Most OpenOffice.org objects provide the method supportsService because they have the interface com.sun.star.lang.XServiceInfo. &lt;br /&gt;
&lt;br /&gt;
In the above example, the OpenOffice.org Basic command, &amp;#039;&amp;#039;&amp;#039;HasUnoInterfaces&amp;#039;&amp;#039;&amp;#039; checks that the current document has the interface com.sun.star.lang.XServiceInfo, because if it doesn&amp;#039;t have that interface then it doesn&amp;#039;t have the method supportsService, and a run time error would occur if such an object tried to access its nonexistent method. &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;SupportsService&amp;#039;&amp;#039;&amp;#039; is a method which returns true if the specified service is available. The above examples checks for a service to determine the type of document that is currently active.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==X-Ray tool==&lt;br /&gt;
Using HasUnoInterfaces and supportsService gives information about an object at run time, but checking an object like this would be a nightmare for learning? Thankfully Bernard Marcelly has come to our rescue with the X-Ray tool. The X-Ray tool is available from: [[http://ooomacros.org/dev.php#101416 ooomacros]]. Download the zip file, unzip the document, open the document in OpenOffice.org, follow the instructions for installation and set-up. &lt;br /&gt;
&lt;br /&gt;
Part of the X-Ray tool set-up is to specify a local copy of the OpenOffice.org SDK. Download the OpenOffice.org SDK from and extract it. &lt;br /&gt;
&lt;br /&gt;
In the above example, at the start of the code, there are two commented lines (comments start with an apostrophe): &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039;basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
&amp;#039;xray.xray thisComponent&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Now that you have the X-Ray tool installed, uncomment these lines (remove the apostrophes) and rerun the macro. From version 5 of Xray the command simply becomes xray.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;BasicLibraries&amp;#039;&amp;#039;&amp;#039; is an OpenOffice.org Basic command that returns an object for accessing the OpenOffice.org libraries. The &amp;lt;tt&amp;gt;loadLibrary&amp;lt;/tt&amp;gt; method ensures that the routines in that library are available for use. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;xray.xray&amp;lt;/tt&amp;gt; specifies the xray library and the xray subroutine within that library, thisComponent is the object that is being passed to xray for introspection. &lt;br /&gt;
&lt;br /&gt;
To find the object that you want to work with often requires finding or creating it starting from either StarDesktop or thisComponent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Desktop, documents, and current selection==&lt;br /&gt;
StarDesktop and ThisComponent are OpenOffice.org Basic commands that refer to the application and currently active document respectively. &lt;br /&gt;
&lt;br /&gt;
Unlike Microsoft Office, OpenOffice.org is one application with different components. When running some code it maybe useful to check which component is currently active. The above code demonstrates how that checking process can be done. &lt;br /&gt;
&lt;br /&gt;
The Desktop that StarDesktop refers to is conceptual (historically it actually existed) and can be thought of as the OpenOffice.org application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Creating new documents==&lt;br /&gt;
To create a new text document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/swriter&amp;quot;, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To create a new spreadsheet document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/scalc&amp;quot;, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
An easier approach would be to write a simple function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnNewDoc(sDocType as string)&lt;br /&gt;
fnNewDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/&amp;quot; &amp;amp; sDocType , &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Then creating new documents can be achieved with: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;swriter&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;scalc&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;simpress&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;sdraw&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;smath&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
See http://api.openoffice.org/docs/common/ref/com/sun/star/frame/XComponentLoader.html .&lt;br /&gt;
&lt;br /&gt;
==To open a document==&lt;br /&gt;
The following example shows how to open a file. For information on URLs in OpenOffice.org see [[ URL Basics]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sFile = &amp;quot;C:\Documents and Settings\danny\Desktop\MyCalc.sxc&amp;quot; &amp;#039; Windows&lt;br /&gt;
sFile = &amp;quot;/home/danny/Desktop/MyCalc.sxc&amp;quot; &amp;#039; Linux&lt;br /&gt;
sURL = ConvertToURL(sFile)&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(sURL, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Again it may make sense to make this easier by writing a simple function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnOpenDoc(sFile)&lt;br /&gt;
sURL = ConvertToURL(sFile)&lt;br /&gt;
fnOpenDoc = StarDesktop.loadComponentFromURL(sURL, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Examples of calling the function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = fnOpenDoc(&amp;quot;C:\Documents and Settings\danny\Desktop\MyCalc.sxc&amp;quot;) &amp;#039; Windows&lt;br /&gt;
oDoc = fnOpenDoc(&amp;quot;/home/danny/Desktop/MyCalc.sxc&amp;quot;) &amp;#039; Linux&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Current Selection==&lt;br /&gt;
It is common to want to run some code that effects the current selection. &amp;lt;tt&amp;gt;ThisComponent&amp;lt;/tt&amp;gt; has the method &amp;lt;tt&amp;gt;getCurrentSelection&amp;lt;/tt&amp;gt;. Since many different types of objects could possibly be selected it is common to check that the currently selected object has the service that contains the method that we want to apply to the object. &lt;br /&gt;
&lt;br /&gt;
Edit the main subroutine to the following and rerun it on a text document with different selections. (To select more than one block of text hold down the control key). &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
if fnWhichComponent(thisComponent) = &amp;quot;Text&amp;quot; then&lt;br /&gt;
        oCurSelection = thisComponent.getCurrentSelection()&lt;br /&gt;
        &amp;#039;xray.xray oCurSelection&lt;br /&gt;
        if oCurSelection.supportsService(&amp;quot;com.sun.star.text.TextRanges&amp;quot;) then&lt;br /&gt;
                msgbox &amp;quot;There are &amp;quot; &amp;amp; oCurSelection.getCount() &amp;amp; _&lt;br /&gt;
                 &amp;quot; selections in the current text document.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
With nothing selected the number of selections is one - the insertion point, with one block of text selected the count is still one, but with two blocks of text the count is three - the insertion point and the two blocks of selected text. &lt;br /&gt;
&lt;br /&gt;
Exercise 1: Modify the above code so that it works on selected cell ranges in a spreadsheet. &lt;br /&gt;
&lt;br /&gt;
Question1: For two blocks of cells selected, what would be the count for the number of selections? &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Properties==&lt;br /&gt;
Uncomment &amp;lt;tt&amp;gt;&amp;#039;xray.xray oCurSelection&amp;lt;/tt&amp;gt; so that xray runs, to see that the object that &amp;lt;tt&amp;gt;oCurSelection&amp;lt;/tt&amp;gt; points to has a &amp;quot;property&amp;quot; called &amp;lt;tt&amp;gt;Count&amp;lt;/tt&amp;gt; with a description of &amp;quot;pseudo-prop, read only&amp;quot;. It is possible in OpenOffice.org Basic to write &amp;lt;tt&amp;gt;oCurSelection.count&amp;lt;/tt&amp;gt;, but as this is not possible in all other languages accessing the OpenOffice.org API, this Wiki will try to always use the method approach. (I say try because I have not been in the habit of doing this and sometimes I may forget). &lt;br /&gt;
&lt;br /&gt;
This next example demonstrates changing a property value for the current selections. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
if fnWhichComponent(thisComponent) = &amp;quot;Text&amp;quot; then&lt;br /&gt;
   oCurSelection = thisComponent.getCurrentSelection()&lt;br /&gt;
   if oCurSelection.supportsService(&amp;quot;com.sun.star.text.TextRanges&amp;quot;) then&lt;br /&gt;
      nCount = oCurSelection.Count&lt;br /&gt;
      &amp;#039;xray.xray oCurSelection.getByIndex(0)&lt;br /&gt;
      &amp;#039;Warning: The insertion point will have the same action applied twice&lt;br /&gt;
      &amp;#039;in this case it doesn&amp;#039;t matter, but in others it might.&lt;br /&gt;
      for i = 0 to nCount - 1&lt;br /&gt;
         oCurSelection.getByIndex(i).setPropertyValue(&amp;quot;CharStyleName&amp;quot;, &amp;quot;Strong Emphasis&amp;quot;)&lt;br /&gt;
      next&lt;br /&gt;
   end if&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
In OpenOffice.org Basic it is possible to shorten the assignment line to: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oCurSelection(i).CharStyleName = &amp;quot;Strong Emphasis&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This wiki will try to use the full methods for both indexing and assigning properties. The rationale is that this makes converting the code to other languages easier and also helps the learner to understand what is happening (again I have not been in the habit of doing this so some examples may slip past me). &lt;br /&gt;
&lt;br /&gt;
Exercise 2: Rewrite the above code so that the warning can be removed. &lt;br /&gt;
&lt;br /&gt;
See [[ Current selection]]. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Iterative Access to Subordinate Objects (Enumeration access)=&lt;br /&gt;
Sometimes to access the desired object an enumeration is required. For example paragraphs, within a document or within a selection. &lt;br /&gt;
&lt;br /&gt;
When a Writer document is active and some text is selected, both &amp;lt;tt&amp;gt;thisDocument.getText()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;thisComponent.getCurrentSelection().getByIndex(i)&amp;lt;/tt&amp;gt; have the service: com.sun.star.text.TextRange which has the interface: com.sun.star.container.XContentEnumerationAccess, it is possible to create an enumeration of the paragraphs for the current document or for a particular selection. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; Create enumeration object&lt;br /&gt;
oTextElementEnum = thisComponent.getText().createEnumeration()&lt;br /&gt;
&amp;#039;or thisComponent.getCurrentSelection().getByIndex(i).createEnumeration()&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; loop over all text elements&lt;br /&gt;
while oTextElementEnum.hasMoreElements()&lt;br /&gt;
        oTextElement = oTextElementEnum.nextElement&lt;br /&gt;
        if oTextElement.supportsService(&amp;quot;com.sun.star.text.TextTable&amp;quot;) then&lt;br /&gt;
                MsgBox &amp;quot;The current block contains a table.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
        if oTextElement.supportsService(&amp;quot;com.sun.star.text.Paragraph&amp;quot;) then&lt;br /&gt;
                MsgBox &amp;quot;The current block contains a paragraph.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
wend&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Exercise 3: Extend the above example to display in a message box all text portions that are bold. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Named access=&lt;br /&gt;
Some objects provide named access to a particular type of subordinate object, some others indexed access, and some both named and indexed access. &lt;br /&gt;
&lt;br /&gt;
For example if the current document in OpenOffice.org is a spreadsheet then to access a particular sheet can be done by index access: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oSheet = thisComponent.getSheets.getByIndex(0)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
or named access: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oSheet = thisComponent.getSheets.getByName(&amp;quot;Sheet1&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To check if an object with a particular name already exists use &amp;lt;tt&amp;gt;hasByName&amp;lt;/tt&amp;gt;, for example: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
if thisComponent.getSheets.hasByName(&amp;quot;Sheet1&amp;quot;) then&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To loop through all the available object names can be done like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
mNames = thisComponent.getSheets.getElementnames&lt;br /&gt;
for i = lbound(mNames) to ubound(mNames)&lt;br /&gt;
        msgbox mNames(i)&lt;br /&gt;
next&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Some named subordinate objects also provide the interface:  com.sun.star.container.XNameContainer. This interface defines that such objects should have the following methods: &amp;lt;tt&amp;gt;insertByName&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;replaceByname&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;removeByName&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
E.g. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
thisComponent.getSheets.insertByName(&amp;quot;NewSheet&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Create new objects=&lt;br /&gt;
Some objects have services which implement interfaces to provide specific methods for creating a particular type of object. &lt;br /&gt;
&lt;br /&gt;
For example if the current document is a Writer document then &amp;lt;tt&amp;gt;thisComponent.getText&amp;lt;/tt&amp;gt; is an object that provides the service com.sun.star.text.Text which implements the interface  com.sun.star.text.XSimpleText which defines the methods &amp;lt;tt&amp;gt;createTextCursor&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;createTextCursorByRange&amp;lt;/tt&amp;gt;. Both of these methods create a text cursor for accessing the text of the document. These cursors are quite independent of the view cursor . The view cursor is visible on the screen and is manipulated by the user (and can be manipulated by program control), where as a text cursor is not visible on the screen and is solely used by program control. The following code snippet demonstrates creating a new text cursor, such that it starts at the same location as the viewCursor and is then moved independent of the view cursor. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oVC = thisComponent.getCurrentController.getViewCursor&lt;br /&gt;
oCursor = oVC.getText.createTextCursorByRange(oVC)&lt;br /&gt;
oCursor.gotoStartOfSentence(false)&lt;br /&gt;
oCursor.gotoEndOfSentence(true)&lt;br /&gt;
msgbox oCursor.getString&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Some objects are context dependent and get created using the method &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt; which is defined in the interface com.sun.star.lang.XMultiServiceFactory. For example to add a rectangle to the first page of a drawing document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
dim aPoint as new com.sun.star.awt.Point&lt;br /&gt;
dim aSize as new com.sun.star.awt.Size&lt;br /&gt;
 &lt;br /&gt;
aPoint.x = 1000&lt;br /&gt;
aPoint.y = 1000&lt;br /&gt;
 &lt;br /&gt;
aSize.Width = 10000&lt;br /&gt;
aSize.Height = 10000&lt;br /&gt;
 &lt;br /&gt;
oRectangleShape = thisComponent.createInstance(&amp;quot;com.sun.star.drawing.RectangleShape&amp;quot;)&lt;br /&gt;
oRectangleShape.Size = aSize&lt;br /&gt;
oRectangleShape.Position = aPoint&lt;br /&gt;
 &lt;br /&gt;
thisComponent.getDrawPages.getByIndex(0).add(oRectangleShape)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example also uses UNO structs see below for more information on UNO stucts. &lt;br /&gt;
&lt;br /&gt;
Some objects are context independent to create these objects use the OpenOffice.org Basic command createUnoService. For example to create the equivalent to StarDesktop: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDesktop = createUnoService(&amp;quot;com.sun.star.frame.Desktop&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The process that I use to determine how to access or create an object is as follows: &lt;br /&gt;
&lt;br /&gt;
Does the object already exist if so I should be able to access it from something like &amp;lt;tt&amp;gt;thisComponent&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Will the new object belong to another object, if so does the owner have a specific method for creating the object, if so use it. &lt;br /&gt;
&lt;br /&gt;
The new object will belong to another object, but that object doesn&amp;#039;t provide a specific method for creating it, but does provide &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt;. If the object doesn&amp;#039;t provide &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt; are you sure you are using the correct object, or is it context independent. &lt;br /&gt;
&lt;br /&gt;
I have found working out how to create an object to be quite difficult with existing documentation so I hope that this document/wiki will eventually make this clear. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==UNO structs==&lt;br /&gt;
UNO structures can be declared using the OpenOffice.org Basic command &amp;lt;tt&amp;gt;dim&amp;lt;/tt&amp;gt;: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
dim aPoint as new com.sun.star.awt.Point&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Or by using the OpenOffice.org Basic command &amp;lt;tt&amp;gt;createUnoStruct&amp;lt;/tt&amp;gt;: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
aPoint = createUnoStruct(&amp;quot;com.sun.star.awt.Point&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|When declaring UNO structs case is important. Note that everything upto the name of the struct is lowercase, and that the name of the struct is in TitleCase.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Creating Listeners and Handlers==&lt;br /&gt;
Through the user interface it is possible to assign macros to some events: &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org versions 1.1.x: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Configure… &amp;gt; Events&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org versions 1.9.x and above: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Customize… &amp;gt; Events&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
It is also possible to assign macros to a wider range of events using the OpenOffice.org Basic command CreateUnoListener. This same command is used for creating both listeners and handlers. A listener checks for an event and always allows other listeners to respond to the event as well. A handler listens for an event, and can optionally consume the event so that other listeners don&amp;#039;t get to act on it. &lt;br /&gt;
&lt;br /&gt;
The following example creates a keyHandler: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
global IannzExampleKeyHandler&lt;br /&gt;
 &lt;br /&gt;
sub SetupKeyHandler&lt;br /&gt;
oController = thisComponent.currentController&lt;br /&gt;
IannzExampleKeyHandler = CreateUnoListener(&amp;quot;KeyHandler_&amp;quot;,&amp;quot;com.sun.star.awt.XKeyHandler&amp;quot;)&lt;br /&gt;
oController.addKeyHandler(IannzExampleKeyHandler) &amp;#039; Register the listener&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
sub RemoveKeyHandler&lt;br /&gt;
thisComponent.currentController.removeKeyHandler(IannzExampleKeyHandler)&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
sub KeyHandler_disposing&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function KeyHandler_keyReleased(oKeyEvent as new com.sun.star.awt.KeyHandler) as boolean&lt;br /&gt;
        KeyHandler_keyReleased = False    &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function KeyHandler_keyPressed(oKeyEvent as new com.sun.star.awt.KeyHandler) as boolean&lt;br /&gt;
KeyHandler_keyPressed = false   &amp;#039;Let other listeners handle the event&lt;br /&gt;
if oKeyEvent.modifiers = com.sun.star.awt.KeyModifier.MOD2 then &amp;#039;Control key was pressed&lt;br /&gt;
        if oKeyEvent.keyCode = com.sun.star.awt.Key.Q then&lt;br /&gt;
                msgbox &amp;quot;Alt + Q was pressed&amp;quot;&lt;br /&gt;
                KeyHandler_keyPressed = true    &amp;#039;Don&amp;#039;t let other listeners process this event&lt;br /&gt;
        end if&lt;br /&gt;
end if&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
A variable declared as global keeps its value even after the macro exits. In this case we want to be able to use this variable later to remove the handler. As variables declared globally could be used in other libraries to try and avoid conflict I start all my global variables with Iannz my registered name for the OpenOffice.org web site. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;sub SetupKeyHandler&amp;lt;/tt&amp;gt; sets up the handler. The first parameter to CreateUnoListener is the staring name for the methods that will be called when that type of event occurs in this example .&amp;lt;tt&amp;gt;&amp;quot;KeyHandler_&amp;quot;&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
The second parameter is the name of the interface for the listener or handler, &amp;quot;com.sun.star.awt.XKeyHandler&amp;quot;. The name is case sensitive, everything up to and including the module name is always lowercase, the name of the interface always starts with &amp;quot;X&amp;quot; and the remainder is in TitleCase. &lt;br /&gt;
&lt;br /&gt;
Use the SDK to find out what methods the interface must supply. You must supply routines for all of these methods even if you don&amp;#039;t intend to use them. You also need to supply a disposing method. The names of these routines start with the string given in the first parameter to CreateUnoListener , in this example &amp;lt;tt&amp;gt;&amp;quot;KeyHandler_&amp;quot;&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Thus in the example there is &amp;lt;tt&amp;gt;KeyHandler_disposing&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;KeyHandler_keyReleased&amp;lt;/tt&amp;gt; which don&amp;#039;t actually do anything but are required, and &amp;lt;tt&amp;gt;KeyHandler_keyPressed&amp;lt;/tt&amp;gt; which actually does the job. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;sub RemoveKeyHandler&amp;lt;/tt&amp;gt; demonstrates how to remove the handler.&lt;br /&gt;
&lt;br /&gt;
=OpenOffice.org constants=&lt;br /&gt;
The above example uses OpenOffice.org constants. &lt;br /&gt;
&lt;br /&gt;
E.g. com.sun.star.awt.KeyModifier.MOD2&lt;br /&gt;
&lt;br /&gt;
OpenOffice.org constants are case sensitive. Everything up to and including the module name is always lowercase. The constant group is in TitleCase. The actual constant name is always UPPERCASE. &lt;br /&gt;
&lt;br /&gt;
Programmers not using OpenOffice.org Basic may not have access to these constants. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Using the recorder=&lt;br /&gt;
See [[ The OpenOffice.org recorder and UNO dispatch calls]] section for a discussion on recording UNO Dispatch commands versus writing API calls.&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Extensions_development_basic&amp;diff=7468</id>
		<title>Extensions development basic</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Extensions_development_basic&amp;diff=7468"/>
		<updated>2006-04-04T05:58:44Z</updated>

		<summary type="html">&lt;p&gt;Iannz: /* Variables */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;Getting started tutorial&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
This page provides a getting started guide for writing macros in OpenOffice.org Basic. It assumes some prior programming knowledge. Please edit this page to make it more readable. I hope you will find it useful in getting started.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Where do I write the code?=&lt;br /&gt;
OpenOffice.org Basic code is stored in modules within libraries. A library can be: &lt;br /&gt;
&lt;br /&gt;
*Shared (for a network install - OOo Macros &amp;amp; Dialogs) &lt;br /&gt;
*Just for the current user (My Macros &amp;amp; Dialogs) &lt;br /&gt;
*Within a document or template, so that its code is only available when that document is open.Within a document or template, so that its code is only available when that document is open. &lt;br /&gt;
Libraries not stored in a document or template (that is libraries that are shared or for the current user) are referred to as &amp;#039;&amp;#039;&amp;#039;OpenOffice.org libraries&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
To determine the actual folders that contain the OpenOffice.org libraries see:&amp;lt;br&amp;gt; &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Options… &amp;gt; OpenOffice.org &amp;gt; Paths &amp;gt; BASIC&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|Do not copy or move libraries using operating system commands. Use the macro organizer or package manager instead.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Modules within libraries have a maximum size of 64kb. A library can contain up to 16,000 modules. &lt;br /&gt;
&lt;br /&gt;
For more information see online help for: Modules and Libraries. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Accessing the IDE=&lt;br /&gt;
To access the IDE for the first time: &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org 1.1.x: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Macro… &amp;gt;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org 1.9.x and above: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Organize macros &amp;gt; OpenOffice.org Basic… &amp;gt;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
To get started we will use Module1 in the Standard library which is stored for the current user only: &lt;br /&gt;
&lt;br /&gt;
Type a name for the new macro: &amp;#039;&amp;#039;&amp;#039;HelloWorld&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
In the macro from listbox select &amp;#039;&amp;#039;&amp;#039;Standard&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Click &amp;#039;&amp;#039;&amp;#039;New&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
You should now see something like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
REM  *****  BASIC  *****&lt;br /&gt;
 &lt;br /&gt;
Sub Main&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
 &lt;br /&gt;
Sub HelloWorld&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The cursor will be positioned at the start of the &amp;lt;tt&amp;gt;Sub HelloWorld&amp;lt;/tt&amp;gt; line. &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|Now that while the IDE is running it can be accessed from the OpenOffice.org Window menu, or the task panel provided by the operating system.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Entering the code=&lt;br /&gt;
Select and delete: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
REM  *****  BASIC  *****&lt;br /&gt;
 &lt;br /&gt;
Sub Main&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Below the line &amp;quot;Sub HelloWorld&amp;quot; type &amp;lt;tt&amp;gt;msgbox &amp;quot;Hello World!&amp;quot;&amp;lt;/tt&amp;gt;, so that the editor looks like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Sub HelloWorld&lt;br /&gt;
msgbox &amp;quot;Hello World!&amp;quot;&lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Notes:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|The IDE does not provide code completion or help with command syntax as you type, but to get help on a Basic command position the cursor in the command and press F1.&amp;lt;br&amp;gt; OpenOffice.org Basic commands are not case sensitive. Thus msgbox, MSGBOX and Msgbox will all work.&amp;lt;br&amp;gt; Strings are enclosed in double quotes.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Running the code=&lt;br /&gt;
There are several ways of running the Basic code, these include: &lt;br /&gt;
&lt;br /&gt;
Directly from the IDE. There is a run button on the macro bar (by default the third control on the second toolbar). This will run the first macro in the current module. &lt;br /&gt;
&lt;br /&gt;
From the tools menu: (Version 1.1.x) &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Macro…&amp;#039;&amp;#039;&amp;#039;; (Version 1.9.x and above) &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macro &amp;gt; Run Macro…&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a [[ key press]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a [[ menu entry]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a toolbar button. &lt;br /&gt;
&lt;br /&gt;
Creating a [[ control in a document]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to an event. &lt;br /&gt;
&lt;br /&gt;
For now try running the &amp;quot;HelloWorld&amp;quot; subroutine by clicking the &amp;#039;&amp;#039;&amp;#039;Run&amp;#039;&amp;#039;&amp;#039; button. A small dialog titled &amp;quot;soffice&amp;quot; with the text &amp;quot;Hello World!&amp;quot; and an OK button should be displayed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Saving the code=&lt;br /&gt;
The code gets automatically saved whenever the container for the code gets saved. Thus, if the code is in an OpenOffice.org library (shared or users) then it gets automatically saved when OpenOffice.org exits. If the code is in a library which is part of a document it gets saved whenever the document is saved. &lt;br /&gt;
&lt;br /&gt;
On the Standard toolbar (by default the top toolbar) in the IDE there is a save button. If the code is in a document or template then clicking this button saves the entire document or template. If the code is in an OpenOffice.org library then just the current library gets saved. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Variables=&lt;br /&gt;
It is possible to force variable declaration with &amp;lt;tt&amp;gt;Option Explicit&amp;lt;/tt&amp;gt; at the top of the module. For a discussion on whether to declare variables or not see: [[http://www.oooforum.org/forum/viewtopic.phtml?t=5845 this discussion]]. &lt;br /&gt;
&lt;br /&gt;
In that discussion the initial author of this wiki thought that variables should always be declared. Since then he has changed to not declaring them. In short it is generally a personal preference. In either case, it is the initial authors preference that variables be named according to the following convention, which is used in the examples in this Wiki: &lt;br /&gt;
&lt;br /&gt;
The first letter of the variable name indicates the type of value that the variable is going to hold, as per the following table (based on a table in Tutorial.pdf by Sun) &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Letter&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Meaning&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|-&lt;br /&gt;
|a&lt;br /&gt;
|Structure&lt;br /&gt;
|-&lt;br /&gt;
|b&lt;br /&gt;
|Boolean (TRUE or FALSE)&lt;br /&gt;
|-&lt;br /&gt;
|e&lt;br /&gt;
|Enumeration. This variable can only have one of a limited set of values.&lt;br /&gt;
|-&lt;br /&gt;
|f&lt;br /&gt;
|Float (3.402823 x 1038 to 1.401298 x 10-45. A single variable can take up to four bytes)&amp;lt;br&amp;gt; Double (1.79769313486232 x 10308 to 4.94065645841247 x 10-324. A double variable can take up to eight bytes)&amp;lt;br&amp;gt; Currency (-922337203685477.5808 to +922337203685477.5807 and takes up to eight bytes of memory)&lt;br /&gt;
|-&lt;br /&gt;
|m&lt;br /&gt;
|Array (aka sequence aka matrix)&lt;br /&gt;
|-&lt;br /&gt;
|n&lt;br /&gt;
|Integer (-32768 to 32767.) or&amp;lt;br&amp;gt; Long (-2147483648 and 2147483647).&lt;br /&gt;
|-&lt;br /&gt;
|o&lt;br /&gt;
|Object, service, or interface&lt;br /&gt;
|-&lt;br /&gt;
|s&lt;br /&gt;
|String (A string variable can store up to 65535 Unicode characters).&lt;br /&gt;
|-&lt;br /&gt;
|x&lt;br /&gt;
|Interface, to indicate that only operations of a particular interface of an object are used&lt;br /&gt;
|-&lt;br /&gt;
|v&lt;br /&gt;
|Variant, Any&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Use long descriptive variable names making use of camel case &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|User defined OpenOffice.org Basic variables are not case sensitive. But UNO-API constants are case sensitive.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Convention exceptions to long descriptive names is for index variables where i, j, and k are commonly used, and for when a string is being built-up, where s is commonly used. &lt;br /&gt;
&lt;br /&gt;
Edit sub HelloWorld so that it looks like the following and run it: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub HelloWorld&lt;br /&gt;
dim i as integer &amp;#039;This line is optional&lt;br /&gt;
for i = 0 to 2&lt;br /&gt;
        &amp;#039;These lines are indented for ease of reading only&lt;br /&gt;
        msgbox &amp;quot;Hello World &amp;quot; &amp;amp; i&lt;br /&gt;
next&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
For more information on variables see the online help for &amp;quot;using variables&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=Understanding the OpenOffice.org API=&lt;br /&gt;
This section will start with an example. The remainder of this section aims to give information so that the example can be understood and expanded upon. &lt;br /&gt;
&lt;br /&gt;
Try running the following code with different types of documents being active. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
&amp;#039;basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
&amp;#039;xray.xray thisComponent&lt;br /&gt;
msgbox fnWhichComponent(thisComponent)&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function fnWhichComponent(oDoc) as string&lt;br /&gt;
if HasUnoInterfaces(oDoc, &amp;quot;com.sun.star.lang.XServiceInfo&amp;quot;) then &lt;br /&gt;
   if thisComponent.supportsService (&amp;quot;com.sun.star.text.GenericTextDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Text&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.sheet.SpreadsheetDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Spreadsheet&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.presentation.PresentationDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Presentation&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.drawing.GenericDrawingDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Drawing&amp;quot;&lt;br /&gt;
   else&lt;br /&gt;
      fnWhichComponent = &amp;quot;Oops current document something else&amp;quot;&lt;br /&gt;
   end if&lt;br /&gt;
else&lt;br /&gt;
   fnWhichComponent = &amp;quot;Not a document&amp;quot;&lt;br /&gt;
end if&lt;br /&gt;
End function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subroutine naming convention==&lt;br /&gt;
In the above example the user defined function has a name that starts with the letters &amp;quot;fn&amp;quot;. This is the initial authors convention so that people know that this is a user defined function. Similarly, the initial author uses the convention that user defined subroutines start with the letters &amp;quot;sub&amp;quot;. When learning a language and an API it can be difficult to know what is built-in and what has been defined elsewhere. This document/wiki will use this convention for naming functions and subroutines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Introducing the OpenOffice.org API==&lt;br /&gt;
This section introduces the following terms: &lt;br /&gt;
&lt;br /&gt;
* Interface &lt;br /&gt;
* Module &lt;br /&gt;
* Service &lt;br /&gt;
* Method &lt;br /&gt;
* Property &lt;br /&gt;
&lt;br /&gt;
Understanding the difference between an interface and a service and what a module is, is not essential to being able to write extensions for OpenOffice.org, but it does help interpreting the documentation, and for introspection purposes. You may need to read this section at least twice. &lt;br /&gt;
&lt;br /&gt;
An &amp;#039;&amp;#039;&amp;#039;interface&amp;#039;&amp;#039;&amp;#039; is a &amp;#039;&amp;#039;definition&amp;#039;&amp;#039; of a set of methods (and their arguments) that a service which implements that interface must have. &lt;br /&gt;
&lt;br /&gt;
Interfaces are grouped together in &amp;#039;&amp;#039;&amp;#039;modules&amp;#039;&amp;#039;&amp;#039; for naming purposes. All interfaces (and services) start with the name &amp;quot;com.sun.star&amp;quot; then the name of the module then the name of the interface (or service). &lt;br /&gt;
&lt;br /&gt;
For example most services provide the com.sun.star.beans.XPropertySet interface. This interface is stored in the module &amp;quot;beans&amp;quot; and provides access to the properties of a service. A &amp;#039;&amp;#039;&amp;#039;property&amp;#039;&amp;#039;&amp;#039; is a value where as a &amp;#039;&amp;#039;&amp;#039;method&amp;#039;&amp;#039;&amp;#039; is an action. &lt;br /&gt;
&lt;br /&gt;
An OpenOffice.org object can have many services. &lt;br /&gt;
&lt;br /&gt;
An OpenOffice.org object may have a service, which implements an interface, in which a method description says that another OpenOffice.org object is returned.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Introspection==&lt;br /&gt;
HasUnoInterfaces is an OpenOffice.org Basic function for introspection. See this [[http://www.oooforum.org/forum/viewtopic.phtml?t=7068 link]] for information on introspection in other languages. &lt;br /&gt;
&lt;br /&gt;
HasUnoInterfaces returns true if all of the specified interfaces are available for the specified object. &lt;br /&gt;
&lt;br /&gt;
Most OpenOffice.org objects provide the method supportsService because they have the interface com.sun.star.lang.XServiceInfo. &lt;br /&gt;
&lt;br /&gt;
In the above example, the OpenOffice.org Basic command, &amp;#039;&amp;#039;&amp;#039;HasUnoInterfaces&amp;#039;&amp;#039;&amp;#039; checks that the current document has the interface com.sun.star.lang.XServiceInfo, because if it doesn&amp;#039;t have that interface then it doesn&amp;#039;t have the method supportsService, and a run time error would occur if such an object tried to access its nonexistent method. &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;SupportsService&amp;#039;&amp;#039;&amp;#039; is a method which returns true if the specified service is available. The above examples checks for a service to determine the type of document that is currently active.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==X-Ray tool==&lt;br /&gt;
Using HasUnoInterfaces and supportsService gives information about an object at run time, but checking an object like this would be a nightmare for learning? Thankfully Bernard Marcelly has come to our rescue with the X-Ray tool. The X-Ray tool is available from: [[http://ooomacros.org/dev.php#101416 ooomacros]]. Download the zip file, unzip the document, open the document in OpenOffice.org, follow the instructions for installation and set-up. &lt;br /&gt;
&lt;br /&gt;
Part of the X-Ray tool set-up is to specify a local copy of the OpenOffice.org SDK. Download the OpenOffice.org SDK from and extract it. &lt;br /&gt;
&lt;br /&gt;
In the above example, at the start of the code, there are two commented lines (comments start with an apostrophe): &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039;basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
&amp;#039;xray.xray thisComponent&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Now that you have the X-Ray tool installed, uncomment these lines (remove the apostrophes) and rerun the macro. From version 5 of Xray the command simply becomes xray.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;BasicLibraries&amp;#039;&amp;#039;&amp;#039; is an OpenOffice.org Basic command that returns an object for accessing the OpenOffice.org libraries. The &amp;lt;tt&amp;gt;loadLibrary&amp;lt;/tt&amp;gt; method ensures that the routines in that library are available for use. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;xray.xray&amp;lt;/tt&amp;gt; specifies the xray library and the xray subroutine within that library, thisComponent is the object that is being passed to xray for introspection. &lt;br /&gt;
&lt;br /&gt;
To find the object that you want to work with often requires finding or creating it starting from either StarDesktop or thisComponent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Desktop, documents, and current selection==&lt;br /&gt;
StarDesktop and ThisComponent are OpenOffice.org Basic commands that refer to the application and currently active document respectively. &lt;br /&gt;
&lt;br /&gt;
Unlike Microsoft Office, OpenOffice.org is one application with different components. When running some code it maybe useful to check which component is currently active. The above code demonstrates how that checking process can be done. &lt;br /&gt;
&lt;br /&gt;
The Desktop that StarDesktop refers to is conceptual (historically it actually existed) and can be thought of as the OpenOffice.org application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Creating new documents==&lt;br /&gt;
To create a new text document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/swriter&amp;quot;, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To create a new spreadsheet document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/scalc&amp;quot;, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
An easier approach would be to write a simple function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnNewDoc(sDocType as string)&lt;br /&gt;
fnNewDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/&amp;quot; &amp;amp; sDocType , &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Then creating new documents can be achieved with: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;swriter&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;scalc&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;simpress&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;sdraw&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;smath&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
See [[ loadComponentFromUrl]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==To open a document==&lt;br /&gt;
The following example shows how to open a file. For information on URLs in OpenOffice.org see [[ URL Basics]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sFile = &amp;quot;C:\Documents and Settings\danny\Desktop\MyCalc.sxc&amp;quot; &amp;#039; Windows&lt;br /&gt;
sFile = &amp;quot;/home/danny/Desktop/MyCalc.sxc&amp;quot; &amp;#039; Linux&lt;br /&gt;
sURL = ConvertToURL(sFile)&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(sURL, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Again it may make sense to make this easier by writing a simple function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnOpenDoc(sFile)&lt;br /&gt;
sURL = ConvertToURL(sFile)&lt;br /&gt;
fnOpenDoc = StarDesktop.loadComponentFromURL(sURL, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Examples of calling the function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = fnOpenDoc(&amp;quot;C:\Documents and Settings\danny\Desktop\MyCalc.sxc&amp;quot;) &amp;#039; Windows&lt;br /&gt;
oDoc = fnOpenDoc(&amp;quot;/home/danny/Desktop/MyCalc.sxc&amp;quot;) &amp;#039; Linux&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Current Selection==&lt;br /&gt;
It is common to want to run some code that effects the current selection. &amp;lt;tt&amp;gt;ThisComponent&amp;lt;/tt&amp;gt; has the method &amp;lt;tt&amp;gt;getCurrentSelection&amp;lt;/tt&amp;gt;. Since many different types of objects could possibly be selected it is common to check that the currently selected object has the service that contains the method that we want to apply to the object. &lt;br /&gt;
&lt;br /&gt;
Edit the main subroutine to the following and rerun it on a text document with different selections. (To select more than one block of text hold down the control key). &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
if fnWhichComponent(thisComponent) = &amp;quot;Text&amp;quot; then&lt;br /&gt;
        oCurSelection = thisComponent.getCurrentSelection()&lt;br /&gt;
        &amp;#039;xray.xray oCurSelection&lt;br /&gt;
        if oCurSelection.supportsService(&amp;quot;com.sun.star.text.TextRanges&amp;quot;) then&lt;br /&gt;
                msgbox &amp;quot;There are &amp;quot; &amp;amp; oCurSelection.getCount() &amp;amp; _&lt;br /&gt;
                 &amp;quot; selections in the current text document.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
With nothing selected the number of selections is one - the insertion point, with one block of text selected the count is still one, but with two blocks of text the count is three - the insertion point and the two blocks of selected text. &lt;br /&gt;
&lt;br /&gt;
Exercise 1: Modify the above code so that it works on selected cell ranges in a spreadsheet. &lt;br /&gt;
&lt;br /&gt;
Question1: For two blocks of cells selected, what would be the count for the number of selections? &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Properties==&lt;br /&gt;
Uncomment &amp;lt;tt&amp;gt;&amp;#039;xray.xray oCurSelection&amp;lt;/tt&amp;gt; so that xray runs, to see that the object that &amp;lt;tt&amp;gt;oCurSelection&amp;lt;/tt&amp;gt; points to has a &amp;quot;property&amp;quot; called &amp;lt;tt&amp;gt;Count&amp;lt;/tt&amp;gt; with a description of &amp;quot;pseudo-prop, read only&amp;quot;. It is possible in OpenOffice.org Basic to write &amp;lt;tt&amp;gt;oCurSelection.count&amp;lt;/tt&amp;gt;, but as this is not possible in all other languages accessing the OpenOffice.org API, this Wiki will try to always use the method approach. (I say try because I have not been in the habit of doing this and sometimes I may forget). &lt;br /&gt;
&lt;br /&gt;
This next example demonstrates changing a property value for the current selections. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
if fnWhichComponent(thisComponent) = &amp;quot;Text&amp;quot; then&lt;br /&gt;
   oCurSelection = thisComponent.getCurrentSelection()&lt;br /&gt;
   if oCurSelection.supportsService(&amp;quot;com.sun.star.text.TextRanges&amp;quot;) then&lt;br /&gt;
      nCount = oCurSelection.Count&lt;br /&gt;
      &amp;#039;xray.xray oCurSelection.getByIndex(0)&lt;br /&gt;
      &amp;#039;Warning: The insertion point will have the same action applied twice&lt;br /&gt;
      &amp;#039;in this case it doesn&amp;#039;t matter, but in others it might.&lt;br /&gt;
      for i = 0 to nCount - 1&lt;br /&gt;
         oCurSelection.getByIndex(i).setPropertyValue(&amp;quot;CharStyleName&amp;quot;, &amp;quot;Strong Emphasis&amp;quot;)&lt;br /&gt;
      next&lt;br /&gt;
   end if&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
In OpenOffice.org Basic it is possible to shorten the assignment line to: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oCurSelection(i).CharStyleName = &amp;quot;Strong Emphasis&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This wiki will try to use the full methods for both indexing and assigning properties. The rationale is that this makes converting the code to other languages easier and also helps the learner to understand what is happening (again I have not been in the habit of doing this so some examples may slip past me). &lt;br /&gt;
&lt;br /&gt;
Exercise 2: Rewrite the above code so that the warning can be removed. &lt;br /&gt;
&lt;br /&gt;
See [[ Current selection]]. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Iterative Access to Subordinate Objects (Enumeration access)=&lt;br /&gt;
Sometimes to access the desired object an enumeration is required. For example paragraphs, within a document or within a selection. &lt;br /&gt;
&lt;br /&gt;
When a Writer document is active and some text is selected, both &amp;lt;tt&amp;gt;thisDocument.getText()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;thisComponent.getCurrentSelection().getByIndex(i)&amp;lt;/tt&amp;gt; have the service: com.sun.star.text.TextRange which has the interface: com.sun.star.container.XContentEnumerationAccess, it is possible to create an enumeration of the paragraphs for the current document or for a particular selection. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; Create enumeration object&lt;br /&gt;
oTextElementEnum = thisComponent.getText().createEnumeration()&lt;br /&gt;
&amp;#039;or thisComponent.getCurrentSelection().getByIndex(i).createEnumeration()&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; loop over all text elements&lt;br /&gt;
while oTextElementEnum.hasMoreElements()&lt;br /&gt;
        oTextElement = oTextElementEnum.nextElement&lt;br /&gt;
        if oTextElement.supportsService(&amp;quot;com.sun.star.text.TextTable&amp;quot;) then&lt;br /&gt;
                MsgBox &amp;quot;The current block contains a table.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
        if oTextElement.supportsService(&amp;quot;com.sun.star.text.Paragraph&amp;quot;) then&lt;br /&gt;
                MsgBox &amp;quot;The current block contains a paragraph.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
wend&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Exercise 3: Extend the above example to display in a message box all text portions that are bold. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Named access=&lt;br /&gt;
Some objects provide named access to a particular type of subordinate object, some others indexed access, and some both named and indexed access. &lt;br /&gt;
&lt;br /&gt;
For example if the current document in OpenOffice.org is a spreadsheet then to access a particular sheet can be done by index access: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oSheet = thisComponent.getSheets.getByIndex(0)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
or named access: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oSheet = thisComponent.getSheets.getByName(&amp;quot;Sheet1&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To check if an object with a particular name already exists use &amp;lt;tt&amp;gt;hasByName&amp;lt;/tt&amp;gt;, for example: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
if thisComponent.getSheets.hasByName(&amp;quot;Sheet1&amp;quot;) then&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To loop through all the available object names can be done like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
mNames = thisComponent.getSheets.getElementnames&lt;br /&gt;
for i = lbound(mNames) to ubound(mNames)&lt;br /&gt;
        msgbox mNames(i)&lt;br /&gt;
next&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Some named subordinate objects also provide the interface:  com.sun.star.container.XNameContainer. This interface defines that such objects should have the following methods: &amp;lt;tt&amp;gt;insertByName&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;replaceByname&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;removeByName&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
E.g. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
thisComponent.getSheets.insertByName(&amp;quot;NewSheet&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Create new objects=&lt;br /&gt;
Some objects have services which implement interfaces to provide specific methods for creating a particular type of object. &lt;br /&gt;
&lt;br /&gt;
For example if the current document is a Writer document then &amp;lt;tt&amp;gt;thisComponent.getText&amp;lt;/tt&amp;gt; is an object that provides the service com.sun.star.text.Text which implements the interface  com.sun.star.text.XSimpleText which defines the methods &amp;lt;tt&amp;gt;createTextCursor&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;createTextCursorByRange&amp;lt;/tt&amp;gt;. Both of these methods create a text cursor for accessing the text of the document. These cursors are quite independent of the view cursor . The view cursor is visible on the screen and is manipulated by the user (and can be manipulated by program control), where as a text cursor is not visible on the screen and is solely used by program control. The following code snippet demonstrates creating a new text cursor, such that it starts at the same location as the viewCursor and is then moved independent of the view cursor. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oVC = thisComponent.getCurrentController.getViewCursor&lt;br /&gt;
oCursor = oVC.getText.createTextCursorByRange(oVC)&lt;br /&gt;
oCursor.gotoStartOfSentence(false)&lt;br /&gt;
oCursor.gotoEndOfSentence(true)&lt;br /&gt;
msgbox oCursor.getString&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Some objects are context dependent and get created using the method &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt; which is defined in the interface com.sun.star.lang.XMultiServiceFactory. For example to add a rectangle to the first page of a drawing document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
dim aPoint as new com.sun.star.awt.Point&lt;br /&gt;
dim aSize as new com.sun.star.awt.Size&lt;br /&gt;
 &lt;br /&gt;
aPoint.x = 1000&lt;br /&gt;
aPoint.y = 1000&lt;br /&gt;
 &lt;br /&gt;
aSize.Width = 10000&lt;br /&gt;
aSize.Height = 10000&lt;br /&gt;
 &lt;br /&gt;
oRectangleShape = thisComponent.createInstance(&amp;quot;com.sun.star.drawing.RectangleShape&amp;quot;)&lt;br /&gt;
oRectangleShape.Size = aSize&lt;br /&gt;
oRectangleShape.Position = aPoint&lt;br /&gt;
 &lt;br /&gt;
thisComponent.getDrawPages.getByIndex(0).add(oRectangleShape)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example also uses UNO structs see below for more information on UNO stucts. &lt;br /&gt;
&lt;br /&gt;
Some objects are context independent to create these objects use the OpenOffice.org Basic command createUnoService. For example to create the equivalent to StarDesktop: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDesktop = createUnoService(&amp;quot;com.sun.star.frame.Desktop&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The process that I use to determine how to access or create an object is as follows: &lt;br /&gt;
&lt;br /&gt;
Does the object already exist if so I should be able to access it from something like &amp;lt;tt&amp;gt;thisComponent&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Will the new object belong to another object, if so does the owner have a specific method for creating the object, if so use it. &lt;br /&gt;
&lt;br /&gt;
The new object will belong to another object, but that object doesn&amp;#039;t provide a specific method for creating it, but does provide &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt;. If the object doesn&amp;#039;t provide &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt; are you sure you are using the correct object, or is it context independent. &lt;br /&gt;
&lt;br /&gt;
I have found working out how to create an object to be quite difficult with existing documentation so I hope that this document/wiki will eventually make this clear. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==UNO structs==&lt;br /&gt;
UNO structures can be declared using the OpenOffice.org Basic command &amp;lt;tt&amp;gt;dim&amp;lt;/tt&amp;gt;: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
dim aPoint as new com.sun.star.awt.Point&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Or by using the OpenOffice.org Basic command &amp;lt;tt&amp;gt;createUnoStruct&amp;lt;/tt&amp;gt;: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
aPoint = createUnoStruct(&amp;quot;com.sun.star.awt.Point&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|When declaring UNO structs case is important. Note that everything upto the name of the struct is lowercase, and that the name of the struct is in TitleCase.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Creating Listeners and Handlers==&lt;br /&gt;
Through the user interface it is possible to assign macros to some events: &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org versions 1.1.x: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Configure… &amp;gt; Events&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org versions 1.9.x and above: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Customize… &amp;gt; Events&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
It is also possible to assign macros to a wider range of events using the OpenOffice.org Basic command CreateUnoListener. This same command is used for creating both listeners and handlers. A listener checks for an event and always allows other listeners to respond to the event as well. A handler listens for an event, and can optionally consume the event so that other listeners don&amp;#039;t get to act on it. &lt;br /&gt;
&lt;br /&gt;
The following example creates a keyHandler: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
global IannzExampleKeyHandler&lt;br /&gt;
 &lt;br /&gt;
sub SetupKeyHandler&lt;br /&gt;
oController = thisComponent.currentController&lt;br /&gt;
IannzExampleKeyHandler = CreateUnoListener(&amp;quot;KeyHandler_&amp;quot;,&amp;quot;com.sun.star.awt.XKeyHandler&amp;quot;)&lt;br /&gt;
oController.addKeyHandler(IannzExampleKeyHandler) &amp;#039; Register the listener&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
sub RemoveKeyHandler&lt;br /&gt;
thisComponent.currentController.removeKeyHandler(IannzExampleKeyHandler)&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
sub KeyHandler_disposing&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function KeyHandler_keyReleased(oKeyEvent as new com.sun.star.awt.KeyHandler) as boolean&lt;br /&gt;
        KeyHandler_keyReleased = False    &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function KeyHandler_keyPressed(oKeyEvent as new com.sun.star.awt.KeyHandler) as boolean&lt;br /&gt;
KeyHandler_keyPressed = false   &amp;#039;Let other listeners handle the event&lt;br /&gt;
if oKeyEvent.modifiers = com.sun.star.awt.KeyModifier.MOD2 then &amp;#039;Control key was pressed&lt;br /&gt;
        if oKeyEvent.keyCode = com.sun.star.awt.Key.Q then&lt;br /&gt;
                msgbox &amp;quot;Alt + Q was pressed&amp;quot;&lt;br /&gt;
                KeyHandler_keyPressed = true    &amp;#039;Don&amp;#039;t let other listeners process this event&lt;br /&gt;
        end if&lt;br /&gt;
end if&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
A variable declared as global keeps its value even after the macro exits. In this case we want to be able to use this variable later to remove the handler. As variables declared globally could be used in other libraries to try and avoid conflict I start all my global variables with Iannz my registered name for the OpenOffice.org web site. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;sub SetupKeyHandler&amp;lt;/tt&amp;gt; sets up the handler. The first parameter to CreateUnoListener is the staring name for the methods that will be called when that type of event occurs in this example .&amp;lt;tt&amp;gt;&amp;quot;KeyHandler_&amp;quot;&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
The second parameter is the name of the interface for the listener or handler, &amp;quot;com.sun.star.awt.XKeyHandler&amp;quot;. The name is case sensitive, everything up to and including the module name is always lowercase, the name of the interface always starts with &amp;quot;X&amp;quot; and the remainder is in TitleCase. &lt;br /&gt;
&lt;br /&gt;
Use the SDK to find out what methods the interface must supply. You must supply routines for all of these methods even if you don&amp;#039;t intend to use them. You also need to supply a disposing method. The names of these routines start with the string given in the first parameter to CreateUnoListener , in this example &amp;lt;tt&amp;gt;&amp;quot;KeyHandler_&amp;quot;&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Thus in the example there is &amp;lt;tt&amp;gt;KeyHandler_disposing&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;KeyHandler_keyReleased&amp;lt;/tt&amp;gt; which don&amp;#039;t actually do anything but are required, and &amp;lt;tt&amp;gt;KeyHandler_keyPressed&amp;lt;/tt&amp;gt; which actually does the job. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;sub RemoveKeyHandler&amp;lt;/tt&amp;gt; demonstrates how to remove the handler.&lt;br /&gt;
&lt;br /&gt;
=OpenOffice.org constants=&lt;br /&gt;
The above example uses OpenOffice.org constants. &lt;br /&gt;
&lt;br /&gt;
E.g. com.sun.star.awt.KeyModifier.MOD2&lt;br /&gt;
&lt;br /&gt;
OpenOffice.org constants are case sensitive. Everything up to and including the module name is always lowercase. The constant group is in TitleCase. The actual constant name is always UPPERCASE. &lt;br /&gt;
&lt;br /&gt;
Programmers not using OpenOffice.org Basic may not have access to these constants. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Using the recorder=&lt;br /&gt;
See [[ The OpenOffice.org recorder and UNO dispatch calls]] section for a discussion on recording UNO Dispatch commands versus writing API calls.&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Menu_entry&amp;diff=7467</id>
		<title>Menu entry</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Menu_entry&amp;diff=7467"/>
		<updated>2006-04-04T05:55:55Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;Adding a menu entry&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
#Tools &amp;gt; Customize… &amp;gt; Menus &lt;br /&gt;
#Select desired menu from thr drop down&lt;br /&gt;
#Selecte the desired location in the listbox&lt;br /&gt;
#Click Add&lt;br /&gt;
#In the category list box: Navigate to the macro by clicking on the + signs next to libraries and click on the module. &lt;br /&gt;
#In the function list box: Click the desired function &lt;br /&gt;
#Click the Add button  &lt;br /&gt;
#Click Close &amp;gt; OK&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Key_press&amp;diff=7464</id>
		<title>Key press</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Key_press&amp;diff=7464"/>
		<updated>2006-04-04T05:51:11Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;Assigning a macro to a key press&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
#Tools &amp;gt; Customize… &amp;gt; Keyboard &lt;br /&gt;
#Select desired key press in the top list box &lt;br /&gt;
#Navigate to where tha macro is stored (scroll to the bottom of the Category list box, then click the plus signs to expand libraries and modules) &lt;br /&gt;
#In the function list box select the desired macro &lt;br /&gt;
#Click the Modify button (top right of dialog) &lt;br /&gt;
#Click OK&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Extensions_development_basic&amp;diff=7463</id>
		<title>Extensions development basic</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Extensions_development_basic&amp;diff=7463"/>
		<updated>2006-04-04T05:48:04Z</updated>

		<summary type="html">&lt;p&gt;Iannz: /* Entering the code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;Getting started tutorial&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
This page provides a getting started guide for writing macros in OpenOffice.org Basic. It assumes some prior programming knowledge. Please edit this page to make it more readable. I hope you will find it useful in getting started.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Where do I write the code?=&lt;br /&gt;
OpenOffice.org Basic code is stored in modules within libraries. A library can be: &lt;br /&gt;
&lt;br /&gt;
*Shared (for a network install - OOo Macros &amp;amp; Dialogs) &lt;br /&gt;
*Just for the current user (My Macros &amp;amp; Dialogs) &lt;br /&gt;
*Within a document or template, so that its code is only available when that document is open.Within a document or template, so that its code is only available when that document is open. &lt;br /&gt;
Libraries not stored in a document or template (that is libraries that are shared or for the current user) are referred to as &amp;#039;&amp;#039;&amp;#039;OpenOffice.org libraries&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
To determine the actual folders that contain the OpenOffice.org libraries see:&amp;lt;br&amp;gt; &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Options… &amp;gt; OpenOffice.org &amp;gt; Paths &amp;gt; BASIC&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|Do not copy or move libraries using operating system commands. Use the macro organizer or package manager instead.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Modules within libraries have a maximum size of 64kb. A library can contain up to 16,000 modules. &lt;br /&gt;
&lt;br /&gt;
For more information see online help for: Modules and Libraries. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Accessing the IDE=&lt;br /&gt;
To access the IDE for the first time: &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org 1.1.x: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Macro… &amp;gt;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org 1.9.x and above: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Organize macros &amp;gt; OpenOffice.org Basic… &amp;gt;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
To get started we will use Module1 in the Standard library which is stored for the current user only: &lt;br /&gt;
&lt;br /&gt;
Type a name for the new macro: &amp;#039;&amp;#039;&amp;#039;HelloWorld&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
In the macro from listbox select &amp;#039;&amp;#039;&amp;#039;Standard&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Click &amp;#039;&amp;#039;&amp;#039;New&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
You should now see something like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
REM  *****  BASIC  *****&lt;br /&gt;
 &lt;br /&gt;
Sub Main&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
 &lt;br /&gt;
Sub HelloWorld&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The cursor will be positioned at the start of the &amp;lt;tt&amp;gt;Sub HelloWorld&amp;lt;/tt&amp;gt; line. &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|Now that while the IDE is running it can be accessed from the OpenOffice.org Window menu, or the task panel provided by the operating system.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Entering the code=&lt;br /&gt;
Select and delete: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
REM  *****  BASIC  *****&lt;br /&gt;
 &lt;br /&gt;
Sub Main&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Below the line &amp;quot;Sub HelloWorld&amp;quot; type &amp;lt;tt&amp;gt;msgbox &amp;quot;Hello World!&amp;quot;&amp;lt;/tt&amp;gt;, so that the editor looks like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Sub HelloWorld&lt;br /&gt;
msgbox &amp;quot;Hello World!&amp;quot;&lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Notes:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|The IDE does not provide code completion or help with command syntax as you type, but to get help on a Basic command position the cursor in the command and press F1.&amp;lt;br&amp;gt; OpenOffice.org Basic commands are not case sensitive. Thus msgbox, MSGBOX and Msgbox will all work.&amp;lt;br&amp;gt; Strings are enclosed in double quotes.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Running the code=&lt;br /&gt;
There are several ways of running the Basic code, these include: &lt;br /&gt;
&lt;br /&gt;
Directly from the IDE. There is a run button on the macro bar (by default the third control on the second toolbar). This will run the first macro in the current module. &lt;br /&gt;
&lt;br /&gt;
From the tools menu: (Version 1.1.x) &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Macro…&amp;#039;&amp;#039;&amp;#039;; (Version 1.9.x and above) &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macro &amp;gt; Run Macro…&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a [[ key press]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a [[ menu entry]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a toolbar button. &lt;br /&gt;
&lt;br /&gt;
Creating a [[ control in a document]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to an event. &lt;br /&gt;
&lt;br /&gt;
For now try running the &amp;quot;HelloWorld&amp;quot; subroutine by clicking the &amp;#039;&amp;#039;&amp;#039;Run&amp;#039;&amp;#039;&amp;#039; button. A small dialog titled &amp;quot;soffice&amp;quot; with the text &amp;quot;Hello World!&amp;quot; and an OK button should be displayed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Saving the code=&lt;br /&gt;
The code gets automatically saved whenever the container for the code gets saved. Thus, if the code is in an OpenOffice.org library (shared or users) then it gets automatically saved when OpenOffice.org exits. If the code is in a library which is part of a document it gets saved whenever the document is saved. &lt;br /&gt;
&lt;br /&gt;
On the Standard toolbar (by default the top toolbar) in the IDE there is a save button. If the code is in a document or template then clicking this button saves the entire document or template. If the code is in an OpenOffice.org library then just the current library gets saved. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Variables=&lt;br /&gt;
It is possible to force variable declaration with &amp;lt;tt&amp;gt;Option Explicit&amp;lt;/tt&amp;gt; at the top of the module. For a discussion on whether to declare variables or not see: [[http://www.oooforum.org/forum/viewtopic.phtml?t=5845 this discussion]]. &lt;br /&gt;
&lt;br /&gt;
In that discussion the initial author of this wiki thought that variables should always be declared. Since then he has changed to not declaring them. In short it is generally a personal preference. In either case, it is the initial authors preference that variables be named according to the following convention, which is used in the examples in this Wiki: &lt;br /&gt;
&lt;br /&gt;
The first letter of the variable name indicates the type of value that the variable is going to hold, as per the following table (based on a table in Tutorial.pdf by Sun) &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Letter&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Meaning&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|-&lt;br /&gt;
|a&lt;br /&gt;
|Structure&lt;br /&gt;
|-&lt;br /&gt;
|b&lt;br /&gt;
|Boolean (TRUE or FALSE)&lt;br /&gt;
|-&lt;br /&gt;
|e&lt;br /&gt;
|Enumeration. This variable can only have one of a limited set of values.&lt;br /&gt;
|-&lt;br /&gt;
|f&lt;br /&gt;
|Float (3.402823 x 1038 to 1.401298 x 10-45. A single variable can take up to four bytes)&amp;lt;br&amp;gt; Double (1.79769313486232 x 10308 to 4.94065645841247 x 10-324. A double variable can take up to eight bytes)&amp;lt;br&amp;gt; Currency (-922337203685477.5808 to +922337203685477.5807 and takes up to eight bytes of memory)&lt;br /&gt;
|-&lt;br /&gt;
|m&lt;br /&gt;
|Array (aka sequence aka matrix)&lt;br /&gt;
|-&lt;br /&gt;
|n&lt;br /&gt;
|Integer (-32768 to 32767.) or&amp;lt;br&amp;gt; Long (-2147483648 and 2147483647).&lt;br /&gt;
|-&lt;br /&gt;
|o&lt;br /&gt;
|Object, service, or interface&lt;br /&gt;
|-&lt;br /&gt;
|s&lt;br /&gt;
|String (A string variable can store up to 65535 Unicode characters).&lt;br /&gt;
|-&lt;br /&gt;
|x&lt;br /&gt;
|Interface, to indicate that only operations of a particular interface of an object are used&lt;br /&gt;
|-&lt;br /&gt;
|v&lt;br /&gt;
|Variant, Any&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Use long descriptive variable names making use of camel case &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|User defined OpenOffice.org Basic variables are not case sensitive. But UNO-API constants are case sensitive.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Convention exceptions to long descriptive names is for index variables where i, j, and k are commonly used, and for when a string is being built-up, where s is commonly used. &lt;br /&gt;
&lt;br /&gt;
Edit sub HelloWorld so that it looks like the following and run it: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub HelloWorld&lt;br /&gt;
dim i as integer &amp;#039;This line is optional&lt;br /&gt;
for i = 0 to 2&lt;br /&gt;
        &amp;#039;These lines are indented for ease of reading only&lt;br /&gt;
        msgbox &amp;quot;Hello World &amp;quot; &amp;amp; i&lt;br /&gt;
next&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
For more information on variables see: [[ using variables]]. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Understanding the OpenOffice.org API=&lt;br /&gt;
This section will start with an example. The remainder of this section aims to give information so that the example can be understood and expanded upon. &lt;br /&gt;
&lt;br /&gt;
Try running the following code with different types of documents being active. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
&amp;#039;basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
&amp;#039;xray.xray thisComponent&lt;br /&gt;
msgbox fnWhichComponent(thisComponent)&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function fnWhichComponent(oDoc) as string&lt;br /&gt;
if HasUnoInterfaces(oDoc, &amp;quot;com.sun.star.lang.XServiceInfo&amp;quot;) then &lt;br /&gt;
   if thisComponent.supportsService (&amp;quot;com.sun.star.text.GenericTextDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Text&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.sheet.SpreadsheetDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Spreadsheet&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.presentation.PresentationDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Presentation&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.drawing.GenericDrawingDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Drawing&amp;quot;&lt;br /&gt;
   else&lt;br /&gt;
      fnWhichComponent = &amp;quot;Oops current document something else&amp;quot;&lt;br /&gt;
   end if&lt;br /&gt;
else&lt;br /&gt;
   fnWhichComponent = &amp;quot;Not a document&amp;quot;&lt;br /&gt;
end if&lt;br /&gt;
End function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subroutine naming convention==&lt;br /&gt;
In the above example the user defined function has a name that starts with the letters &amp;quot;fn&amp;quot;. This is the initial authors convention so that people know that this is a user defined function. Similarly, the initial author uses the convention that user defined subroutines start with the letters &amp;quot;sub&amp;quot;. When learning a language and an API it can be difficult to know what is built-in and what has been defined elsewhere. This document/wiki will use this convention for naming functions and subroutines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Introducing the OpenOffice.org API==&lt;br /&gt;
This section introduces the following terms: &lt;br /&gt;
&lt;br /&gt;
* Interface &lt;br /&gt;
* Module &lt;br /&gt;
* Service &lt;br /&gt;
* Method &lt;br /&gt;
* Property &lt;br /&gt;
&lt;br /&gt;
Understanding the difference between an interface and a service and what a module is, is not essential to being able to write extensions for OpenOffice.org, but it does help interpreting the documentation, and for introspection purposes. You may need to read this section at least twice. &lt;br /&gt;
&lt;br /&gt;
An &amp;#039;&amp;#039;&amp;#039;interface&amp;#039;&amp;#039;&amp;#039; is a &amp;#039;&amp;#039;definition&amp;#039;&amp;#039; of a set of methods (and their arguments) that a service which implements that interface must have. &lt;br /&gt;
&lt;br /&gt;
Interfaces are grouped together in &amp;#039;&amp;#039;&amp;#039;modules&amp;#039;&amp;#039;&amp;#039; for naming purposes. All interfaces (and services) start with the name &amp;quot;com.sun.star&amp;quot; then the name of the module then the name of the interface (or service). &lt;br /&gt;
&lt;br /&gt;
For example most services provide the com.sun.star.beans.XPropertySet interface. This interface is stored in the module &amp;quot;beans&amp;quot; and provides access to the properties of a service. A &amp;#039;&amp;#039;&amp;#039;property&amp;#039;&amp;#039;&amp;#039; is a value where as a &amp;#039;&amp;#039;&amp;#039;method&amp;#039;&amp;#039;&amp;#039; is an action. &lt;br /&gt;
&lt;br /&gt;
An OpenOffice.org object can have many services. &lt;br /&gt;
&lt;br /&gt;
An OpenOffice.org object may have a service, which implements an interface, in which a method description says that another OpenOffice.org object is returned.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Introspection==&lt;br /&gt;
HasUnoInterfaces is an OpenOffice.org Basic function for introspection. See this [[http://www.oooforum.org/forum/viewtopic.phtml?t=7068 link]] for information on introspection in other languages. &lt;br /&gt;
&lt;br /&gt;
HasUnoInterfaces returns true if all of the specified interfaces are available for the specified object. &lt;br /&gt;
&lt;br /&gt;
Most OpenOffice.org objects provide the method supportsService because they have the interface com.sun.star.lang.XServiceInfo. &lt;br /&gt;
&lt;br /&gt;
In the above example, the OpenOffice.org Basic command, &amp;#039;&amp;#039;&amp;#039;HasUnoInterfaces&amp;#039;&amp;#039;&amp;#039; checks that the current document has the interface com.sun.star.lang.XServiceInfo, because if it doesn&amp;#039;t have that interface then it doesn&amp;#039;t have the method supportsService, and a run time error would occur if such an object tried to access its nonexistent method. &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;SupportsService&amp;#039;&amp;#039;&amp;#039; is a method which returns true if the specified service is available. The above examples checks for a service to determine the type of document that is currently active.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==X-Ray tool==&lt;br /&gt;
Using HasUnoInterfaces and supportsService gives information about an object at run time, but checking an object like this would be a nightmare for learning? Thankfully Bernard Marcelly has come to our rescue with the X-Ray tool. The X-Ray tool is available from: [[http://ooomacros.org/dev.php#101416 ooomacros]]. Download the zip file, unzip the document, open the document in OpenOffice.org, follow the instructions for installation and set-up. &lt;br /&gt;
&lt;br /&gt;
Part of the X-Ray tool set-up is to specify a local copy of the OpenOffice.org SDK. Download the OpenOffice.org SDK from and extract it. &lt;br /&gt;
&lt;br /&gt;
In the above example, at the start of the code, there are two commented lines (comments start with an apostrophe): &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039;basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
&amp;#039;xray.xray thisComponent&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Now that you have the X-Ray tool installed, uncomment these lines (remove the apostrophes) and rerun the macro. From version 5 of Xray the command simply becomes xray.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;BasicLibraries&amp;#039;&amp;#039;&amp;#039; is an OpenOffice.org Basic command that returns an object for accessing the OpenOffice.org libraries. The &amp;lt;tt&amp;gt;loadLibrary&amp;lt;/tt&amp;gt; method ensures that the routines in that library are available for use. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;xray.xray&amp;lt;/tt&amp;gt; specifies the xray library and the xray subroutine within that library, thisComponent is the object that is being passed to xray for introspection. &lt;br /&gt;
&lt;br /&gt;
To find the object that you want to work with often requires finding or creating it starting from either StarDesktop or thisComponent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Desktop, documents, and current selection==&lt;br /&gt;
StarDesktop and ThisComponent are OpenOffice.org Basic commands that refer to the application and currently active document respectively. &lt;br /&gt;
&lt;br /&gt;
Unlike Microsoft Office, OpenOffice.org is one application with different components. When running some code it maybe useful to check which component is currently active. The above code demonstrates how that checking process can be done. &lt;br /&gt;
&lt;br /&gt;
The Desktop that StarDesktop refers to is conceptual (historically it actually existed) and can be thought of as the OpenOffice.org application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Creating new documents==&lt;br /&gt;
To create a new text document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/swriter&amp;quot;, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To create a new spreadsheet document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/scalc&amp;quot;, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
An easier approach would be to write a simple function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnNewDoc(sDocType as string)&lt;br /&gt;
fnNewDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/&amp;quot; &amp;amp; sDocType , &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Then creating new documents can be achieved with: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;swriter&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;scalc&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;simpress&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;sdraw&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;smath&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
See [[ loadComponentFromUrl]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==To open a document==&lt;br /&gt;
The following example shows how to open a file. For information on URLs in OpenOffice.org see [[ URL Basics]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sFile = &amp;quot;C:\Documents and Settings\danny\Desktop\MyCalc.sxc&amp;quot; &amp;#039; Windows&lt;br /&gt;
sFile = &amp;quot;/home/danny/Desktop/MyCalc.sxc&amp;quot; &amp;#039; Linux&lt;br /&gt;
sURL = ConvertToURL(sFile)&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(sURL, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Again it may make sense to make this easier by writing a simple function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnOpenDoc(sFile)&lt;br /&gt;
sURL = ConvertToURL(sFile)&lt;br /&gt;
fnOpenDoc = StarDesktop.loadComponentFromURL(sURL, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Examples of calling the function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = fnOpenDoc(&amp;quot;C:\Documents and Settings\danny\Desktop\MyCalc.sxc&amp;quot;) &amp;#039; Windows&lt;br /&gt;
oDoc = fnOpenDoc(&amp;quot;/home/danny/Desktop/MyCalc.sxc&amp;quot;) &amp;#039; Linux&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Current Selection==&lt;br /&gt;
It is common to want to run some code that effects the current selection. &amp;lt;tt&amp;gt;ThisComponent&amp;lt;/tt&amp;gt; has the method &amp;lt;tt&amp;gt;getCurrentSelection&amp;lt;/tt&amp;gt;. Since many different types of objects could possibly be selected it is common to check that the currently selected object has the service that contains the method that we want to apply to the object. &lt;br /&gt;
&lt;br /&gt;
Edit the main subroutine to the following and rerun it on a text document with different selections. (To select more than one block of text hold down the control key). &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
if fnWhichComponent(thisComponent) = &amp;quot;Text&amp;quot; then&lt;br /&gt;
        oCurSelection = thisComponent.getCurrentSelection()&lt;br /&gt;
        &amp;#039;xray.xray oCurSelection&lt;br /&gt;
        if oCurSelection.supportsService(&amp;quot;com.sun.star.text.TextRanges&amp;quot;) then&lt;br /&gt;
                msgbox &amp;quot;There are &amp;quot; &amp;amp; oCurSelection.getCount() &amp;amp; _&lt;br /&gt;
                 &amp;quot; selections in the current text document.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
With nothing selected the number of selections is one - the insertion point, with one block of text selected the count is still one, but with two blocks of text the count is three - the insertion point and the two blocks of selected text. &lt;br /&gt;
&lt;br /&gt;
Exercise 1: Modify the above code so that it works on selected cell ranges in a spreadsheet. &lt;br /&gt;
&lt;br /&gt;
Question1: For two blocks of cells selected, what would be the count for the number of selections? &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Properties==&lt;br /&gt;
Uncomment &amp;lt;tt&amp;gt;&amp;#039;xray.xray oCurSelection&amp;lt;/tt&amp;gt; so that xray runs, to see that the object that &amp;lt;tt&amp;gt;oCurSelection&amp;lt;/tt&amp;gt; points to has a &amp;quot;property&amp;quot; called &amp;lt;tt&amp;gt;Count&amp;lt;/tt&amp;gt; with a description of &amp;quot;pseudo-prop, read only&amp;quot;. It is possible in OpenOffice.org Basic to write &amp;lt;tt&amp;gt;oCurSelection.count&amp;lt;/tt&amp;gt;, but as this is not possible in all other languages accessing the OpenOffice.org API, this Wiki will try to always use the method approach. (I say try because I have not been in the habit of doing this and sometimes I may forget). &lt;br /&gt;
&lt;br /&gt;
This next example demonstrates changing a property value for the current selections. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
if fnWhichComponent(thisComponent) = &amp;quot;Text&amp;quot; then&lt;br /&gt;
   oCurSelection = thisComponent.getCurrentSelection()&lt;br /&gt;
   if oCurSelection.supportsService(&amp;quot;com.sun.star.text.TextRanges&amp;quot;) then&lt;br /&gt;
      nCount = oCurSelection.Count&lt;br /&gt;
      &amp;#039;xray.xray oCurSelection.getByIndex(0)&lt;br /&gt;
      &amp;#039;Warning: The insertion point will have the same action applied twice&lt;br /&gt;
      &amp;#039;in this case it doesn&amp;#039;t matter, but in others it might.&lt;br /&gt;
      for i = 0 to nCount - 1&lt;br /&gt;
         oCurSelection.getByIndex(i).setPropertyValue(&amp;quot;CharStyleName&amp;quot;, &amp;quot;Strong Emphasis&amp;quot;)&lt;br /&gt;
      next&lt;br /&gt;
   end if&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
In OpenOffice.org Basic it is possible to shorten the assignment line to: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oCurSelection(i).CharStyleName = &amp;quot;Strong Emphasis&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This wiki will try to use the full methods for both indexing and assigning properties. The rationale is that this makes converting the code to other languages easier and also helps the learner to understand what is happening (again I have not been in the habit of doing this so some examples may slip past me). &lt;br /&gt;
&lt;br /&gt;
Exercise 2: Rewrite the above code so that the warning can be removed. &lt;br /&gt;
&lt;br /&gt;
See [[ Current selection]]. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Iterative Access to Subordinate Objects (Enumeration access)=&lt;br /&gt;
Sometimes to access the desired object an enumeration is required. For example paragraphs, within a document or within a selection. &lt;br /&gt;
&lt;br /&gt;
When a Writer document is active and some text is selected, both &amp;lt;tt&amp;gt;thisDocument.getText()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;thisComponent.getCurrentSelection().getByIndex(i)&amp;lt;/tt&amp;gt; have the service: com.sun.star.text.TextRange which has the interface: com.sun.star.container.XContentEnumerationAccess, it is possible to create an enumeration of the paragraphs for the current document or for a particular selection. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; Create enumeration object&lt;br /&gt;
oTextElementEnum = thisComponent.getText().createEnumeration()&lt;br /&gt;
&amp;#039;or thisComponent.getCurrentSelection().getByIndex(i).createEnumeration()&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; loop over all text elements&lt;br /&gt;
while oTextElementEnum.hasMoreElements()&lt;br /&gt;
        oTextElement = oTextElementEnum.nextElement&lt;br /&gt;
        if oTextElement.supportsService(&amp;quot;com.sun.star.text.TextTable&amp;quot;) then&lt;br /&gt;
                MsgBox &amp;quot;The current block contains a table.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
        if oTextElement.supportsService(&amp;quot;com.sun.star.text.Paragraph&amp;quot;) then&lt;br /&gt;
                MsgBox &amp;quot;The current block contains a paragraph.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
wend&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Exercise 3: Extend the above example to display in a message box all text portions that are bold. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Named access=&lt;br /&gt;
Some objects provide named access to a particular type of subordinate object, some others indexed access, and some both named and indexed access. &lt;br /&gt;
&lt;br /&gt;
For example if the current document in OpenOffice.org is a spreadsheet then to access a particular sheet can be done by index access: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oSheet = thisComponent.getSheets.getByIndex(0)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
or named access: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oSheet = thisComponent.getSheets.getByName(&amp;quot;Sheet1&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To check if an object with a particular name already exists use &amp;lt;tt&amp;gt;hasByName&amp;lt;/tt&amp;gt;, for example: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
if thisComponent.getSheets.hasByName(&amp;quot;Sheet1&amp;quot;) then&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To loop through all the available object names can be done like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
mNames = thisComponent.getSheets.getElementnames&lt;br /&gt;
for i = lbound(mNames) to ubound(mNames)&lt;br /&gt;
        msgbox mNames(i)&lt;br /&gt;
next&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Some named subordinate objects also provide the interface:  com.sun.star.container.XNameContainer. This interface defines that such objects should have the following methods: &amp;lt;tt&amp;gt;insertByName&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;replaceByname&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;removeByName&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
E.g. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
thisComponent.getSheets.insertByName(&amp;quot;NewSheet&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Create new objects=&lt;br /&gt;
Some objects have services which implement interfaces to provide specific methods for creating a particular type of object. &lt;br /&gt;
&lt;br /&gt;
For example if the current document is a Writer document then &amp;lt;tt&amp;gt;thisComponent.getText&amp;lt;/tt&amp;gt; is an object that provides the service com.sun.star.text.Text which implements the interface  com.sun.star.text.XSimpleText which defines the methods &amp;lt;tt&amp;gt;createTextCursor&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;createTextCursorByRange&amp;lt;/tt&amp;gt;. Both of these methods create a text cursor for accessing the text of the document. These cursors are quite independent of the view cursor . The view cursor is visible on the screen and is manipulated by the user (and can be manipulated by program control), where as a text cursor is not visible on the screen and is solely used by program control. The following code snippet demonstrates creating a new text cursor, such that it starts at the same location as the viewCursor and is then moved independent of the view cursor. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oVC = thisComponent.getCurrentController.getViewCursor&lt;br /&gt;
oCursor = oVC.getText.createTextCursorByRange(oVC)&lt;br /&gt;
oCursor.gotoStartOfSentence(false)&lt;br /&gt;
oCursor.gotoEndOfSentence(true)&lt;br /&gt;
msgbox oCursor.getString&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Some objects are context dependent and get created using the method &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt; which is defined in the interface com.sun.star.lang.XMultiServiceFactory. For example to add a rectangle to the first page of a drawing document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
dim aPoint as new com.sun.star.awt.Point&lt;br /&gt;
dim aSize as new com.sun.star.awt.Size&lt;br /&gt;
 &lt;br /&gt;
aPoint.x = 1000&lt;br /&gt;
aPoint.y = 1000&lt;br /&gt;
 &lt;br /&gt;
aSize.Width = 10000&lt;br /&gt;
aSize.Height = 10000&lt;br /&gt;
 &lt;br /&gt;
oRectangleShape = thisComponent.createInstance(&amp;quot;com.sun.star.drawing.RectangleShape&amp;quot;)&lt;br /&gt;
oRectangleShape.Size = aSize&lt;br /&gt;
oRectangleShape.Position = aPoint&lt;br /&gt;
 &lt;br /&gt;
thisComponent.getDrawPages.getByIndex(0).add(oRectangleShape)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example also uses UNO structs see below for more information on UNO stucts. &lt;br /&gt;
&lt;br /&gt;
Some objects are context independent to create these objects use the OpenOffice.org Basic command createUnoService. For example to create the equivalent to StarDesktop: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDesktop = createUnoService(&amp;quot;com.sun.star.frame.Desktop&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The process that I use to determine how to access or create an object is as follows: &lt;br /&gt;
&lt;br /&gt;
Does the object already exist if so I should be able to access it from something like &amp;lt;tt&amp;gt;thisComponent&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Will the new object belong to another object, if so does the owner have a specific method for creating the object, if so use it. &lt;br /&gt;
&lt;br /&gt;
The new object will belong to another object, but that object doesn&amp;#039;t provide a specific method for creating it, but does provide &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt;. If the object doesn&amp;#039;t provide &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt; are you sure you are using the correct object, or is it context independent. &lt;br /&gt;
&lt;br /&gt;
I have found working out how to create an object to be quite difficult with existing documentation so I hope that this document/wiki will eventually make this clear. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==UNO structs==&lt;br /&gt;
UNO structures can be declared using the OpenOffice.org Basic command &amp;lt;tt&amp;gt;dim&amp;lt;/tt&amp;gt;: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
dim aPoint as new com.sun.star.awt.Point&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Or by using the OpenOffice.org Basic command &amp;lt;tt&amp;gt;createUnoStruct&amp;lt;/tt&amp;gt;: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
aPoint = createUnoStruct(&amp;quot;com.sun.star.awt.Point&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|When declaring UNO structs case is important. Note that everything upto the name of the struct is lowercase, and that the name of the struct is in TitleCase.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Creating Listeners and Handlers==&lt;br /&gt;
Through the user interface it is possible to assign macros to some events: &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org versions 1.1.x: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Configure… &amp;gt; Events&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org versions 1.9.x and above: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Customize… &amp;gt; Events&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
It is also possible to assign macros to a wider range of events using the OpenOffice.org Basic command CreateUnoListener. This same command is used for creating both listeners and handlers. A listener checks for an event and always allows other listeners to respond to the event as well. A handler listens for an event, and can optionally consume the event so that other listeners don&amp;#039;t get to act on it. &lt;br /&gt;
&lt;br /&gt;
The following example creates a keyHandler: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
global IannzExampleKeyHandler&lt;br /&gt;
 &lt;br /&gt;
sub SetupKeyHandler&lt;br /&gt;
oController = thisComponent.currentController&lt;br /&gt;
IannzExampleKeyHandler = CreateUnoListener(&amp;quot;KeyHandler_&amp;quot;,&amp;quot;com.sun.star.awt.XKeyHandler&amp;quot;)&lt;br /&gt;
oController.addKeyHandler(IannzExampleKeyHandler) &amp;#039; Register the listener&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
sub RemoveKeyHandler&lt;br /&gt;
thisComponent.currentController.removeKeyHandler(IannzExampleKeyHandler)&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
sub KeyHandler_disposing&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function KeyHandler_keyReleased(oKeyEvent as new com.sun.star.awt.KeyHandler) as boolean&lt;br /&gt;
        KeyHandler_keyReleased = False    &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function KeyHandler_keyPressed(oKeyEvent as new com.sun.star.awt.KeyHandler) as boolean&lt;br /&gt;
KeyHandler_keyPressed = false   &amp;#039;Let other listeners handle the event&lt;br /&gt;
if oKeyEvent.modifiers = com.sun.star.awt.KeyModifier.MOD2 then &amp;#039;Control key was pressed&lt;br /&gt;
        if oKeyEvent.keyCode = com.sun.star.awt.Key.Q then&lt;br /&gt;
                msgbox &amp;quot;Alt + Q was pressed&amp;quot;&lt;br /&gt;
                KeyHandler_keyPressed = true    &amp;#039;Don&amp;#039;t let other listeners process this event&lt;br /&gt;
        end if&lt;br /&gt;
end if&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
A variable declared as global keeps its value even after the macro exits. In this case we want to be able to use this variable later to remove the handler. As variables declared globally could be used in other libraries to try and avoid conflict I start all my global variables with Iannz my registered name for the OpenOffice.org web site. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;sub SetupKeyHandler&amp;lt;/tt&amp;gt; sets up the handler. The first parameter to CreateUnoListener is the staring name for the methods that will be called when that type of event occurs in this example .&amp;lt;tt&amp;gt;&amp;quot;KeyHandler_&amp;quot;&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
The second parameter is the name of the interface for the listener or handler, &amp;quot;com.sun.star.awt.XKeyHandler&amp;quot;. The name is case sensitive, everything up to and including the module name is always lowercase, the name of the interface always starts with &amp;quot;X&amp;quot; and the remainder is in TitleCase. &lt;br /&gt;
&lt;br /&gt;
Use the SDK to find out what methods the interface must supply. You must supply routines for all of these methods even if you don&amp;#039;t intend to use them. You also need to supply a disposing method. The names of these routines start with the string given in the first parameter to CreateUnoListener , in this example &amp;lt;tt&amp;gt;&amp;quot;KeyHandler_&amp;quot;&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Thus in the example there is &amp;lt;tt&amp;gt;KeyHandler_disposing&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;KeyHandler_keyReleased&amp;lt;/tt&amp;gt; which don&amp;#039;t actually do anything but are required, and &amp;lt;tt&amp;gt;KeyHandler_keyPressed&amp;lt;/tt&amp;gt; which actually does the job. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;sub RemoveKeyHandler&amp;lt;/tt&amp;gt; demonstrates how to remove the handler.&lt;br /&gt;
&lt;br /&gt;
=OpenOffice.org constants=&lt;br /&gt;
The above example uses OpenOffice.org constants. &lt;br /&gt;
&lt;br /&gt;
E.g. com.sun.star.awt.KeyModifier.MOD2&lt;br /&gt;
&lt;br /&gt;
OpenOffice.org constants are case sensitive. Everything up to and including the module name is always lowercase. The constant group is in TitleCase. The actual constant name is always UPPERCASE. &lt;br /&gt;
&lt;br /&gt;
Programmers not using OpenOffice.org Basic may not have access to these constants. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Using the recorder=&lt;br /&gt;
See [[ The OpenOffice.org recorder and UNO dispatch calls]] section for a discussion on recording UNO Dispatch commands versus writing API calls.&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Extensions_development_basic&amp;diff=7462</id>
		<title>Extensions development basic</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Extensions_development_basic&amp;diff=7462"/>
		<updated>2006-04-04T05:46:52Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;Getting started tutorial&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
This page provides a getting started guide for writing macros in OpenOffice.org Basic. It assumes some prior programming knowledge. Please edit this page to make it more readable. I hope you will find it useful in getting started.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Where do I write the code?=&lt;br /&gt;
OpenOffice.org Basic code is stored in modules within libraries. A library can be: &lt;br /&gt;
&lt;br /&gt;
*Shared (for a network install - OOo Macros &amp;amp; Dialogs) &lt;br /&gt;
*Just for the current user (My Macros &amp;amp; Dialogs) &lt;br /&gt;
*Within a document or template, so that its code is only available when that document is open.Within a document or template, so that its code is only available when that document is open. &lt;br /&gt;
Libraries not stored in a document or template (that is libraries that are shared or for the current user) are referred to as &amp;#039;&amp;#039;&amp;#039;OpenOffice.org libraries&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
To determine the actual folders that contain the OpenOffice.org libraries see:&amp;lt;br&amp;gt; &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Options… &amp;gt; OpenOffice.org &amp;gt; Paths &amp;gt; BASIC&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|Do not copy or move libraries using operating system commands. Use the macro organizer or package manager instead.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Modules within libraries have a maximum size of 64kb. A library can contain up to 16,000 modules. &lt;br /&gt;
&lt;br /&gt;
For more information see online help for: Modules and Libraries. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Accessing the IDE=&lt;br /&gt;
To access the IDE for the first time: &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org 1.1.x: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Macro… &amp;gt;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org 1.9.x and above: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Organize macros &amp;gt; OpenOffice.org Basic… &amp;gt;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
To get started we will use Module1 in the Standard library which is stored for the current user only: &lt;br /&gt;
&lt;br /&gt;
Type a name for the new macro: &amp;#039;&amp;#039;&amp;#039;HelloWorld&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
In the macro from listbox select &amp;#039;&amp;#039;&amp;#039;Standard&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Click &amp;#039;&amp;#039;&amp;#039;New&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
You should now see something like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
REM  *****  BASIC  *****&lt;br /&gt;
 &lt;br /&gt;
Sub Main&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
 &lt;br /&gt;
Sub HelloWorld&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The cursor will be positioned at the start of the &amp;lt;tt&amp;gt;Sub HelloWorld&amp;lt;/tt&amp;gt; line. &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|Now that while the IDE is running it can be accessed from the OpenOffice.org Window menu, or the task panel provided by the operating system.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Entering the code=&lt;br /&gt;
Select and delete: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
REM  *****  BASIC  *****&lt;br /&gt;
 &lt;br /&gt;
Sub Main&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Below the line &amp;quot;Sub HelloWorld&amp;quot; type [[ msgbox]]&amp;lt;tt&amp;gt; &amp;quot;Hello World!&amp;quot;&amp;lt;/tt&amp;gt;, so that the editor looks like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Sub HelloWorld&lt;br /&gt;
msgbox &amp;quot;Hello World!&amp;quot;&lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Notes:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|The IDE does not provide code completion or help with command syntax as you type, but to get help on a Basic command position the cursor in the command and press F1.&amp;lt;br&amp;gt; OpenOffice.org Basic commands are not case sensitive. Thus msgbox, MSGBOX and Msgbox will all work.&amp;lt;br&amp;gt; Strings are enclosed in double quotes.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Running the code=&lt;br /&gt;
There are several ways of running the Basic code, these include: &lt;br /&gt;
&lt;br /&gt;
Directly from the IDE. There is a run button on the macro bar (by default the third control on the second toolbar). This will run the first macro in the current module. &lt;br /&gt;
&lt;br /&gt;
From the tools menu: (Version 1.1.x) &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Macro…&amp;#039;&amp;#039;&amp;#039;; (Version 1.9.x and above) &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macro &amp;gt; Run Macro…&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a [[ key press]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a [[ menu entry]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a toolbar button. &lt;br /&gt;
&lt;br /&gt;
Creating a [[ control in a document]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to an event. &lt;br /&gt;
&lt;br /&gt;
For now try running the &amp;quot;HelloWorld&amp;quot; subroutine by clicking the &amp;#039;&amp;#039;&amp;#039;Run&amp;#039;&amp;#039;&amp;#039; button. A small dialog titled &amp;quot;soffice&amp;quot; with the text &amp;quot;Hello World!&amp;quot; and an OK button should be displayed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Saving the code=&lt;br /&gt;
The code gets automatically saved whenever the container for the code gets saved. Thus, if the code is in an OpenOffice.org library (shared or users) then it gets automatically saved when OpenOffice.org exits. If the code is in a library which is part of a document it gets saved whenever the document is saved. &lt;br /&gt;
&lt;br /&gt;
On the Standard toolbar (by default the top toolbar) in the IDE there is a save button. If the code is in a document or template then clicking this button saves the entire document or template. If the code is in an OpenOffice.org library then just the current library gets saved. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Variables=&lt;br /&gt;
It is possible to force variable declaration with &amp;lt;tt&amp;gt;Option Explicit&amp;lt;/tt&amp;gt; at the top of the module. For a discussion on whether to declare variables or not see: [[http://www.oooforum.org/forum/viewtopic.phtml?t=5845 this discussion]]. &lt;br /&gt;
&lt;br /&gt;
In that discussion the initial author of this wiki thought that variables should always be declared. Since then he has changed to not declaring them. In short it is generally a personal preference. In either case, it is the initial authors preference that variables be named according to the following convention, which is used in the examples in this Wiki: &lt;br /&gt;
&lt;br /&gt;
The first letter of the variable name indicates the type of value that the variable is going to hold, as per the following table (based on a table in Tutorial.pdf by Sun) &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Letter&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Meaning&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|-&lt;br /&gt;
|a&lt;br /&gt;
|Structure&lt;br /&gt;
|-&lt;br /&gt;
|b&lt;br /&gt;
|Boolean (TRUE or FALSE)&lt;br /&gt;
|-&lt;br /&gt;
|e&lt;br /&gt;
|Enumeration. This variable can only have one of a limited set of values.&lt;br /&gt;
|-&lt;br /&gt;
|f&lt;br /&gt;
|Float (3.402823 x 1038 to 1.401298 x 10-45. A single variable can take up to four bytes)&amp;lt;br&amp;gt; Double (1.79769313486232 x 10308 to 4.94065645841247 x 10-324. A double variable can take up to eight bytes)&amp;lt;br&amp;gt; Currency (-922337203685477.5808 to +922337203685477.5807 and takes up to eight bytes of memory)&lt;br /&gt;
|-&lt;br /&gt;
|m&lt;br /&gt;
|Array (aka sequence aka matrix)&lt;br /&gt;
|-&lt;br /&gt;
|n&lt;br /&gt;
|Integer (-32768 to 32767.) or&amp;lt;br&amp;gt; Long (-2147483648 and 2147483647).&lt;br /&gt;
|-&lt;br /&gt;
|o&lt;br /&gt;
|Object, service, or interface&lt;br /&gt;
|-&lt;br /&gt;
|s&lt;br /&gt;
|String (A string variable can store up to 65535 Unicode characters).&lt;br /&gt;
|-&lt;br /&gt;
|x&lt;br /&gt;
|Interface, to indicate that only operations of a particular interface of an object are used&lt;br /&gt;
|-&lt;br /&gt;
|v&lt;br /&gt;
|Variant, Any&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Use long descriptive variable names making use of camel case &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|User defined OpenOffice.org Basic variables are not case sensitive. But UNO-API constants are case sensitive.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Convention exceptions to long descriptive names is for index variables where i, j, and k are commonly used, and for when a string is being built-up, where s is commonly used. &lt;br /&gt;
&lt;br /&gt;
Edit sub HelloWorld so that it looks like the following and run it: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub HelloWorld&lt;br /&gt;
dim i as integer &amp;#039;This line is optional&lt;br /&gt;
for i = 0 to 2&lt;br /&gt;
        &amp;#039;These lines are indented for ease of reading only&lt;br /&gt;
        msgbox &amp;quot;Hello World &amp;quot; &amp;amp; i&lt;br /&gt;
next&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
For more information on variables see: [[ using variables]]. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Understanding the OpenOffice.org API=&lt;br /&gt;
This section will start with an example. The remainder of this section aims to give information so that the example can be understood and expanded upon. &lt;br /&gt;
&lt;br /&gt;
Try running the following code with different types of documents being active. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
&amp;#039;basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
&amp;#039;xray.xray thisComponent&lt;br /&gt;
msgbox fnWhichComponent(thisComponent)&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function fnWhichComponent(oDoc) as string&lt;br /&gt;
if HasUnoInterfaces(oDoc, &amp;quot;com.sun.star.lang.XServiceInfo&amp;quot;) then &lt;br /&gt;
   if thisComponent.supportsService (&amp;quot;com.sun.star.text.GenericTextDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Text&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.sheet.SpreadsheetDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Spreadsheet&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.presentation.PresentationDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Presentation&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.drawing.GenericDrawingDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Drawing&amp;quot;&lt;br /&gt;
   else&lt;br /&gt;
      fnWhichComponent = &amp;quot;Oops current document something else&amp;quot;&lt;br /&gt;
   end if&lt;br /&gt;
else&lt;br /&gt;
   fnWhichComponent = &amp;quot;Not a document&amp;quot;&lt;br /&gt;
end if&lt;br /&gt;
End function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subroutine naming convention==&lt;br /&gt;
In the above example the user defined function has a name that starts with the letters &amp;quot;fn&amp;quot;. This is the initial authors convention so that people know that this is a user defined function. Similarly, the initial author uses the convention that user defined subroutines start with the letters &amp;quot;sub&amp;quot;. When learning a language and an API it can be difficult to know what is built-in and what has been defined elsewhere. This document/wiki will use this convention for naming functions and subroutines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Introducing the OpenOffice.org API==&lt;br /&gt;
This section introduces the following terms: &lt;br /&gt;
&lt;br /&gt;
* Interface &lt;br /&gt;
* Module &lt;br /&gt;
* Service &lt;br /&gt;
* Method &lt;br /&gt;
* Property &lt;br /&gt;
&lt;br /&gt;
Understanding the difference between an interface and a service and what a module is, is not essential to being able to write extensions for OpenOffice.org, but it does help interpreting the documentation, and for introspection purposes. You may need to read this section at least twice. &lt;br /&gt;
&lt;br /&gt;
An &amp;#039;&amp;#039;&amp;#039;interface&amp;#039;&amp;#039;&amp;#039; is a &amp;#039;&amp;#039;definition&amp;#039;&amp;#039; of a set of methods (and their arguments) that a service which implements that interface must have. &lt;br /&gt;
&lt;br /&gt;
Interfaces are grouped together in &amp;#039;&amp;#039;&amp;#039;modules&amp;#039;&amp;#039;&amp;#039; for naming purposes. All interfaces (and services) start with the name &amp;quot;com.sun.star&amp;quot; then the name of the module then the name of the interface (or service). &lt;br /&gt;
&lt;br /&gt;
For example most services provide the com.sun.star.beans.XPropertySet interface. This interface is stored in the module &amp;quot;beans&amp;quot; and provides access to the properties of a service. A &amp;#039;&amp;#039;&amp;#039;property&amp;#039;&amp;#039;&amp;#039; is a value where as a &amp;#039;&amp;#039;&amp;#039;method&amp;#039;&amp;#039;&amp;#039; is an action. &lt;br /&gt;
&lt;br /&gt;
An OpenOffice.org object can have many services. &lt;br /&gt;
&lt;br /&gt;
An OpenOffice.org object may have a service, which implements an interface, in which a method description says that another OpenOffice.org object is returned.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Introspection==&lt;br /&gt;
HasUnoInterfaces is an OpenOffice.org Basic function for introspection. See this [[http://www.oooforum.org/forum/viewtopic.phtml?t=7068 link]] for information on introspection in other languages. &lt;br /&gt;
&lt;br /&gt;
HasUnoInterfaces returns true if all of the specified interfaces are available for the specified object. &lt;br /&gt;
&lt;br /&gt;
Most OpenOffice.org objects provide the method supportsService because they have the interface com.sun.star.lang.XServiceInfo. &lt;br /&gt;
&lt;br /&gt;
In the above example, the OpenOffice.org Basic command, &amp;#039;&amp;#039;&amp;#039;HasUnoInterfaces&amp;#039;&amp;#039;&amp;#039; checks that the current document has the interface com.sun.star.lang.XServiceInfo, because if it doesn&amp;#039;t have that interface then it doesn&amp;#039;t have the method supportsService, and a run time error would occur if such an object tried to access its nonexistent method. &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;SupportsService&amp;#039;&amp;#039;&amp;#039; is a method which returns true if the specified service is available. The above examples checks for a service to determine the type of document that is currently active.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==X-Ray tool==&lt;br /&gt;
Using HasUnoInterfaces and supportsService gives information about an object at run time, but checking an object like this would be a nightmare for learning? Thankfully Bernard Marcelly has come to our rescue with the X-Ray tool. The X-Ray tool is available from: [[http://ooomacros.org/dev.php#101416 ooomacros]]. Download the zip file, unzip the document, open the document in OpenOffice.org, follow the instructions for installation and set-up. &lt;br /&gt;
&lt;br /&gt;
Part of the X-Ray tool set-up is to specify a local copy of the OpenOffice.org SDK. Download the OpenOffice.org SDK from and extract it. &lt;br /&gt;
&lt;br /&gt;
In the above example, at the start of the code, there are two commented lines (comments start with an apostrophe): &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039;basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
&amp;#039;xray.xray thisComponent&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Now that you have the X-Ray tool installed, uncomment these lines (remove the apostrophes) and rerun the macro. From version 5 of Xray the command simply becomes xray.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;BasicLibraries&amp;#039;&amp;#039;&amp;#039; is an OpenOffice.org Basic command that returns an object for accessing the OpenOffice.org libraries. The &amp;lt;tt&amp;gt;loadLibrary&amp;lt;/tt&amp;gt; method ensures that the routines in that library are available for use. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;xray.xray&amp;lt;/tt&amp;gt; specifies the xray library and the xray subroutine within that library, thisComponent is the object that is being passed to xray for introspection. &lt;br /&gt;
&lt;br /&gt;
To find the object that you want to work with often requires finding or creating it starting from either StarDesktop or thisComponent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Desktop, documents, and current selection==&lt;br /&gt;
StarDesktop and ThisComponent are OpenOffice.org Basic commands that refer to the application and currently active document respectively. &lt;br /&gt;
&lt;br /&gt;
Unlike Microsoft Office, OpenOffice.org is one application with different components. When running some code it maybe useful to check which component is currently active. The above code demonstrates how that checking process can be done. &lt;br /&gt;
&lt;br /&gt;
The Desktop that StarDesktop refers to is conceptual (historically it actually existed) and can be thought of as the OpenOffice.org application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Creating new documents==&lt;br /&gt;
To create a new text document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/swriter&amp;quot;, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To create a new spreadsheet document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/scalc&amp;quot;, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
An easier approach would be to write a simple function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnNewDoc(sDocType as string)&lt;br /&gt;
fnNewDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/&amp;quot; &amp;amp; sDocType , &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Then creating new documents can be achieved with: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;swriter&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;scalc&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;simpress&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;sdraw&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;smath&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
See [[ loadComponentFromUrl]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==To open a document==&lt;br /&gt;
The following example shows how to open a file. For information on URLs in OpenOffice.org see [[ URL Basics]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sFile = &amp;quot;C:\Documents and Settings\danny\Desktop\MyCalc.sxc&amp;quot; &amp;#039; Windows&lt;br /&gt;
sFile = &amp;quot;/home/danny/Desktop/MyCalc.sxc&amp;quot; &amp;#039; Linux&lt;br /&gt;
sURL = ConvertToURL(sFile)&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(sURL, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Again it may make sense to make this easier by writing a simple function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnOpenDoc(sFile)&lt;br /&gt;
sURL = ConvertToURL(sFile)&lt;br /&gt;
fnOpenDoc = StarDesktop.loadComponentFromURL(sURL, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Examples of calling the function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = fnOpenDoc(&amp;quot;C:\Documents and Settings\danny\Desktop\MyCalc.sxc&amp;quot;) &amp;#039; Windows&lt;br /&gt;
oDoc = fnOpenDoc(&amp;quot;/home/danny/Desktop/MyCalc.sxc&amp;quot;) &amp;#039; Linux&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Current Selection==&lt;br /&gt;
It is common to want to run some code that effects the current selection. &amp;lt;tt&amp;gt;ThisComponent&amp;lt;/tt&amp;gt; has the method &amp;lt;tt&amp;gt;getCurrentSelection&amp;lt;/tt&amp;gt;. Since many different types of objects could possibly be selected it is common to check that the currently selected object has the service that contains the method that we want to apply to the object. &lt;br /&gt;
&lt;br /&gt;
Edit the main subroutine to the following and rerun it on a text document with different selections. (To select more than one block of text hold down the control key). &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
if fnWhichComponent(thisComponent) = &amp;quot;Text&amp;quot; then&lt;br /&gt;
        oCurSelection = thisComponent.getCurrentSelection()&lt;br /&gt;
        &amp;#039;xray.xray oCurSelection&lt;br /&gt;
        if oCurSelection.supportsService(&amp;quot;com.sun.star.text.TextRanges&amp;quot;) then&lt;br /&gt;
                msgbox &amp;quot;There are &amp;quot; &amp;amp; oCurSelection.getCount() &amp;amp; _&lt;br /&gt;
                 &amp;quot; selections in the current text document.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
With nothing selected the number of selections is one - the insertion point, with one block of text selected the count is still one, but with two blocks of text the count is three - the insertion point and the two blocks of selected text. &lt;br /&gt;
&lt;br /&gt;
Exercise 1: Modify the above code so that it works on selected cell ranges in a spreadsheet. &lt;br /&gt;
&lt;br /&gt;
Question1: For two blocks of cells selected, what would be the count for the number of selections? &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Properties==&lt;br /&gt;
Uncomment &amp;lt;tt&amp;gt;&amp;#039;xray.xray oCurSelection&amp;lt;/tt&amp;gt; so that xray runs, to see that the object that &amp;lt;tt&amp;gt;oCurSelection&amp;lt;/tt&amp;gt; points to has a &amp;quot;property&amp;quot; called &amp;lt;tt&amp;gt;Count&amp;lt;/tt&amp;gt; with a description of &amp;quot;pseudo-prop, read only&amp;quot;. It is possible in OpenOffice.org Basic to write &amp;lt;tt&amp;gt;oCurSelection.count&amp;lt;/tt&amp;gt;, but as this is not possible in all other languages accessing the OpenOffice.org API, this Wiki will try to always use the method approach. (I say try because I have not been in the habit of doing this and sometimes I may forget). &lt;br /&gt;
&lt;br /&gt;
This next example demonstrates changing a property value for the current selections. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
if fnWhichComponent(thisComponent) = &amp;quot;Text&amp;quot; then&lt;br /&gt;
   oCurSelection = thisComponent.getCurrentSelection()&lt;br /&gt;
   if oCurSelection.supportsService(&amp;quot;com.sun.star.text.TextRanges&amp;quot;) then&lt;br /&gt;
      nCount = oCurSelection.Count&lt;br /&gt;
      &amp;#039;xray.xray oCurSelection.getByIndex(0)&lt;br /&gt;
      &amp;#039;Warning: The insertion point will have the same action applied twice&lt;br /&gt;
      &amp;#039;in this case it doesn&amp;#039;t matter, but in others it might.&lt;br /&gt;
      for i = 0 to nCount - 1&lt;br /&gt;
         oCurSelection.getByIndex(i).setPropertyValue(&amp;quot;CharStyleName&amp;quot;, &amp;quot;Strong Emphasis&amp;quot;)&lt;br /&gt;
      next&lt;br /&gt;
   end if&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
In OpenOffice.org Basic it is possible to shorten the assignment line to: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oCurSelection(i).CharStyleName = &amp;quot;Strong Emphasis&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This wiki will try to use the full methods for both indexing and assigning properties. The rationale is that this makes converting the code to other languages easier and also helps the learner to understand what is happening (again I have not been in the habit of doing this so some examples may slip past me). &lt;br /&gt;
&lt;br /&gt;
Exercise 2: Rewrite the above code so that the warning can be removed. &lt;br /&gt;
&lt;br /&gt;
See [[ Current selection]]. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Iterative Access to Subordinate Objects (Enumeration access)=&lt;br /&gt;
Sometimes to access the desired object an enumeration is required. For example paragraphs, within a document or within a selection. &lt;br /&gt;
&lt;br /&gt;
When a Writer document is active and some text is selected, both &amp;lt;tt&amp;gt;thisDocument.getText()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;thisComponent.getCurrentSelection().getByIndex(i)&amp;lt;/tt&amp;gt; have the service: com.sun.star.text.TextRange which has the interface: com.sun.star.container.XContentEnumerationAccess, it is possible to create an enumeration of the paragraphs for the current document or for a particular selection. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; Create enumeration object&lt;br /&gt;
oTextElementEnum = thisComponent.getText().createEnumeration()&lt;br /&gt;
&amp;#039;or thisComponent.getCurrentSelection().getByIndex(i).createEnumeration()&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; loop over all text elements&lt;br /&gt;
while oTextElementEnum.hasMoreElements()&lt;br /&gt;
        oTextElement = oTextElementEnum.nextElement&lt;br /&gt;
        if oTextElement.supportsService(&amp;quot;com.sun.star.text.TextTable&amp;quot;) then&lt;br /&gt;
                MsgBox &amp;quot;The current block contains a table.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
        if oTextElement.supportsService(&amp;quot;com.sun.star.text.Paragraph&amp;quot;) then&lt;br /&gt;
                MsgBox &amp;quot;The current block contains a paragraph.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
wend&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Exercise 3: Extend the above example to display in a message box all text portions that are bold. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Named access=&lt;br /&gt;
Some objects provide named access to a particular type of subordinate object, some others indexed access, and some both named and indexed access. &lt;br /&gt;
&lt;br /&gt;
For example if the current document in OpenOffice.org is a spreadsheet then to access a particular sheet can be done by index access: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oSheet = thisComponent.getSheets.getByIndex(0)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
or named access: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oSheet = thisComponent.getSheets.getByName(&amp;quot;Sheet1&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To check if an object with a particular name already exists use &amp;lt;tt&amp;gt;hasByName&amp;lt;/tt&amp;gt;, for example: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
if thisComponent.getSheets.hasByName(&amp;quot;Sheet1&amp;quot;) then&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To loop through all the available object names can be done like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
mNames = thisComponent.getSheets.getElementnames&lt;br /&gt;
for i = lbound(mNames) to ubound(mNames)&lt;br /&gt;
        msgbox mNames(i)&lt;br /&gt;
next&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Some named subordinate objects also provide the interface:  com.sun.star.container.XNameContainer. This interface defines that such objects should have the following methods: &amp;lt;tt&amp;gt;insertByName&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;replaceByname&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;removeByName&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
E.g. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
thisComponent.getSheets.insertByName(&amp;quot;NewSheet&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Create new objects=&lt;br /&gt;
Some objects have services which implement interfaces to provide specific methods for creating a particular type of object. &lt;br /&gt;
&lt;br /&gt;
For example if the current document is a Writer document then &amp;lt;tt&amp;gt;thisComponent.getText&amp;lt;/tt&amp;gt; is an object that provides the service com.sun.star.text.Text which implements the interface  com.sun.star.text.XSimpleText which defines the methods &amp;lt;tt&amp;gt;createTextCursor&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;createTextCursorByRange&amp;lt;/tt&amp;gt;. Both of these methods create a text cursor for accessing the text of the document. These cursors are quite independent of the view cursor . The view cursor is visible on the screen and is manipulated by the user (and can be manipulated by program control), where as a text cursor is not visible on the screen and is solely used by program control. The following code snippet demonstrates creating a new text cursor, such that it starts at the same location as the viewCursor and is then moved independent of the view cursor. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oVC = thisComponent.getCurrentController.getViewCursor&lt;br /&gt;
oCursor = oVC.getText.createTextCursorByRange(oVC)&lt;br /&gt;
oCursor.gotoStartOfSentence(false)&lt;br /&gt;
oCursor.gotoEndOfSentence(true)&lt;br /&gt;
msgbox oCursor.getString&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Some objects are context dependent and get created using the method &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt; which is defined in the interface com.sun.star.lang.XMultiServiceFactory. For example to add a rectangle to the first page of a drawing document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
dim aPoint as new com.sun.star.awt.Point&lt;br /&gt;
dim aSize as new com.sun.star.awt.Size&lt;br /&gt;
 &lt;br /&gt;
aPoint.x = 1000&lt;br /&gt;
aPoint.y = 1000&lt;br /&gt;
 &lt;br /&gt;
aSize.Width = 10000&lt;br /&gt;
aSize.Height = 10000&lt;br /&gt;
 &lt;br /&gt;
oRectangleShape = thisComponent.createInstance(&amp;quot;com.sun.star.drawing.RectangleShape&amp;quot;)&lt;br /&gt;
oRectangleShape.Size = aSize&lt;br /&gt;
oRectangleShape.Position = aPoint&lt;br /&gt;
 &lt;br /&gt;
thisComponent.getDrawPages.getByIndex(0).add(oRectangleShape)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example also uses UNO structs see below for more information on UNO stucts. &lt;br /&gt;
&lt;br /&gt;
Some objects are context independent to create these objects use the OpenOffice.org Basic command createUnoService. For example to create the equivalent to StarDesktop: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDesktop = createUnoService(&amp;quot;com.sun.star.frame.Desktop&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The process that I use to determine how to access or create an object is as follows: &lt;br /&gt;
&lt;br /&gt;
Does the object already exist if so I should be able to access it from something like &amp;lt;tt&amp;gt;thisComponent&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Will the new object belong to another object, if so does the owner have a specific method for creating the object, if so use it. &lt;br /&gt;
&lt;br /&gt;
The new object will belong to another object, but that object doesn&amp;#039;t provide a specific method for creating it, but does provide &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt;. If the object doesn&amp;#039;t provide &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt; are you sure you are using the correct object, or is it context independent. &lt;br /&gt;
&lt;br /&gt;
I have found working out how to create an object to be quite difficult with existing documentation so I hope that this document/wiki will eventually make this clear. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==UNO structs==&lt;br /&gt;
UNO structures can be declared using the OpenOffice.org Basic command &amp;lt;tt&amp;gt;dim&amp;lt;/tt&amp;gt;: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
dim aPoint as new com.sun.star.awt.Point&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Or by using the OpenOffice.org Basic command &amp;lt;tt&amp;gt;createUnoStruct&amp;lt;/tt&amp;gt;: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
aPoint = createUnoStruct(&amp;quot;com.sun.star.awt.Point&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|When declaring UNO structs case is important. Note that everything upto the name of the struct is lowercase, and that the name of the struct is in TitleCase.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Creating Listeners and Handlers==&lt;br /&gt;
Through the user interface it is possible to assign macros to some events: &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org versions 1.1.x: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Configure… &amp;gt; Events&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org versions 1.9.x and above: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Customize… &amp;gt; Events&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
It is also possible to assign macros to a wider range of events using the OpenOffice.org Basic command CreateUnoListener. This same command is used for creating both listeners and handlers. A listener checks for an event and always allows other listeners to respond to the event as well. A handler listens for an event, and can optionally consume the event so that other listeners don&amp;#039;t get to act on it. &lt;br /&gt;
&lt;br /&gt;
The following example creates a keyHandler: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
global IannzExampleKeyHandler&lt;br /&gt;
 &lt;br /&gt;
sub SetupKeyHandler&lt;br /&gt;
oController = thisComponent.currentController&lt;br /&gt;
IannzExampleKeyHandler = CreateUnoListener(&amp;quot;KeyHandler_&amp;quot;,&amp;quot;com.sun.star.awt.XKeyHandler&amp;quot;)&lt;br /&gt;
oController.addKeyHandler(IannzExampleKeyHandler) &amp;#039; Register the listener&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
sub RemoveKeyHandler&lt;br /&gt;
thisComponent.currentController.removeKeyHandler(IannzExampleKeyHandler)&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
sub KeyHandler_disposing&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function KeyHandler_keyReleased(oKeyEvent as new com.sun.star.awt.KeyHandler) as boolean&lt;br /&gt;
        KeyHandler_keyReleased = False    &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function KeyHandler_keyPressed(oKeyEvent as new com.sun.star.awt.KeyHandler) as boolean&lt;br /&gt;
KeyHandler_keyPressed = false   &amp;#039;Let other listeners handle the event&lt;br /&gt;
if oKeyEvent.modifiers = com.sun.star.awt.KeyModifier.MOD2 then &amp;#039;Control key was pressed&lt;br /&gt;
        if oKeyEvent.keyCode = com.sun.star.awt.Key.Q then&lt;br /&gt;
                msgbox &amp;quot;Alt + Q was pressed&amp;quot;&lt;br /&gt;
                KeyHandler_keyPressed = true    &amp;#039;Don&amp;#039;t let other listeners process this event&lt;br /&gt;
        end if&lt;br /&gt;
end if&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
A variable declared as global keeps its value even after the macro exits. In this case we want to be able to use this variable later to remove the handler. As variables declared globally could be used in other libraries to try and avoid conflict I start all my global variables with Iannz my registered name for the OpenOffice.org web site. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;sub SetupKeyHandler&amp;lt;/tt&amp;gt; sets up the handler. The first parameter to CreateUnoListener is the staring name for the methods that will be called when that type of event occurs in this example .&amp;lt;tt&amp;gt;&amp;quot;KeyHandler_&amp;quot;&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
The second parameter is the name of the interface for the listener or handler, &amp;quot;com.sun.star.awt.XKeyHandler&amp;quot;. The name is case sensitive, everything up to and including the module name is always lowercase, the name of the interface always starts with &amp;quot;X&amp;quot; and the remainder is in TitleCase. &lt;br /&gt;
&lt;br /&gt;
Use the SDK to find out what methods the interface must supply. You must supply routines for all of these methods even if you don&amp;#039;t intend to use them. You also need to supply a disposing method. The names of these routines start with the string given in the first parameter to CreateUnoListener , in this example &amp;lt;tt&amp;gt;&amp;quot;KeyHandler_&amp;quot;&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Thus in the example there is &amp;lt;tt&amp;gt;KeyHandler_disposing&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;KeyHandler_keyReleased&amp;lt;/tt&amp;gt; which don&amp;#039;t actually do anything but are required, and &amp;lt;tt&amp;gt;KeyHandler_keyPressed&amp;lt;/tt&amp;gt; which actually does the job. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;sub RemoveKeyHandler&amp;lt;/tt&amp;gt; demonstrates how to remove the handler.&lt;br /&gt;
&lt;br /&gt;
=OpenOffice.org constants=&lt;br /&gt;
The above example uses OpenOffice.org constants. &lt;br /&gt;
&lt;br /&gt;
E.g. com.sun.star.awt.KeyModifier.MOD2&lt;br /&gt;
&lt;br /&gt;
OpenOffice.org constants are case sensitive. Everything up to and including the module name is always lowercase. The constant group is in TitleCase. The actual constant name is always UPPERCASE. &lt;br /&gt;
&lt;br /&gt;
Programmers not using OpenOffice.org Basic may not have access to these constants. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Using the recorder=&lt;br /&gt;
See [[ The OpenOffice.org recorder and UNO dispatch calls]] section for a discussion on recording UNO Dispatch commands versus writing API calls.&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Extensions_development_basic&amp;diff=7461</id>
		<title>Extensions development basic</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Extensions_development_basic&amp;diff=7461"/>
		<updated>2006-04-04T05:46:03Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;Getting started tutorial&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
This page provides agetting started guide for writing macros in OpnOffice.org Basic. It assumes some prior programming knowledge. Please edit this page to make it more readable. I hope you will find it useful in getting started.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Where do I write the code?=&lt;br /&gt;
OpenOffice.org Basic code is stored in modules within libraries. A library can be: &lt;br /&gt;
&lt;br /&gt;
*Shared (for a network install - OOo Macros &amp;amp; Dialogs) &lt;br /&gt;
*Just for the current user (My Macros &amp;amp; Dialogs) &lt;br /&gt;
*Within a document or template, so that its code is only available when that document is open.Within a document or template, so that its code is only available when that document is open. &lt;br /&gt;
Libraries not stored in a document or template (that is libraries that are shared or for the current user) are referred to as &amp;#039;&amp;#039;&amp;#039;OpenOffice.org libraries&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
To determine the actual folders that contain the OpenOffice.org libraries see:&amp;lt;br&amp;gt; &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Options… &amp;gt; OpenOffice.org &amp;gt; Paths &amp;gt; BASIC&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|Do not copy or move libraries using operating system commands. Use the macro organizer or package manager instead.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Modules within libraries have a maximum size of 64kb. A library can contain up to 16,000 modules. &lt;br /&gt;
&lt;br /&gt;
For more information see online help for: Modules and Libraries. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Accessing the IDE=&lt;br /&gt;
To access the IDE for the first time: &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org 1.1.x: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Macro… &amp;gt;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org 1.9.x and above: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Organize macros &amp;gt; OpenOffice.org Basic… &amp;gt;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
To get started we will use Module1 in the Standard library which is stored for the current user only: &lt;br /&gt;
&lt;br /&gt;
Type a name for the new macro: &amp;#039;&amp;#039;&amp;#039;HelloWorld&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
In the macro from listbox select &amp;#039;&amp;#039;&amp;#039;Standard&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Click &amp;#039;&amp;#039;&amp;#039;New&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
You should now see something like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
REM  *****  BASIC  *****&lt;br /&gt;
 &lt;br /&gt;
Sub Main&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
 &lt;br /&gt;
Sub HelloWorld&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The cursor will be positioned at the start of the &amp;lt;tt&amp;gt;Sub HelloWorld&amp;lt;/tt&amp;gt; line. &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|Now that while the IDE is running it can be accessed from the OpenOffice.org Window menu, or the task panel provided by the operating system.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Entering the code=&lt;br /&gt;
Select and delete: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
REM  *****  BASIC  *****&lt;br /&gt;
 &lt;br /&gt;
Sub Main&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Below the line &amp;quot;Sub HelloWorld&amp;quot; type [[ msgbox]]&amp;lt;tt&amp;gt; &amp;quot;Hello World!&amp;quot;&amp;lt;/tt&amp;gt;, so that the editor looks like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Sub HelloWorld&lt;br /&gt;
msgbox &amp;quot;Hello World!&amp;quot;&lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Notes:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|The IDE does not provide code completion or help with command syntax as you type, but to get help on a Basic command position the cursor in the command and press F1.&amp;lt;br&amp;gt; OpenOffice.org Basic commands are not case sensitive. Thus msgbox, MSGBOX and Msgbox will all work.&amp;lt;br&amp;gt; Strings are enclosed in double quotes.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Running the code=&lt;br /&gt;
There are several ways of running the Basic code, these include: &lt;br /&gt;
&lt;br /&gt;
Directly from the IDE. There is a run button on the macro bar (by default the third control on the second toolbar). This will run the first macro in the current module. &lt;br /&gt;
&lt;br /&gt;
From the tools menu: (Version 1.1.x) &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Macro…&amp;#039;&amp;#039;&amp;#039;; (Version 1.9.x and above) &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macro &amp;gt; Run Macro…&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a [[ key press]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a [[ menu entry]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a toolbar button. &lt;br /&gt;
&lt;br /&gt;
Creating a [[ control in a document]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to an event. &lt;br /&gt;
&lt;br /&gt;
For now try running the &amp;quot;HelloWorld&amp;quot; subroutine by clicking the &amp;#039;&amp;#039;&amp;#039;Run&amp;#039;&amp;#039;&amp;#039; button. A small dialog titled &amp;quot;soffice&amp;quot; with the text &amp;quot;Hello World!&amp;quot; and an OK button should be displayed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Saving the code=&lt;br /&gt;
The code gets automatically saved whenever the container for the code gets saved. Thus, if the code is in an OpenOffice.org library (shared or users) then it gets automatically saved when OpenOffice.org exits. If the code is in a library which is part of a document it gets saved whenever the document is saved. &lt;br /&gt;
&lt;br /&gt;
On the Standard toolbar (by default the top toolbar) in the IDE there is a save button. If the code is in a document or template then clicking this button saves the entire document or template. If the code is in an OpenOffice.org library then just the current library gets saved. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Variables=&lt;br /&gt;
It is possible to force variable declaration with &amp;lt;tt&amp;gt;Option Explicit&amp;lt;/tt&amp;gt; at the top of the module. For a discussion on whether to declare variables or not see: [[http://www.oooforum.org/forum/viewtopic.phtml?t=5845 this discussion]]. &lt;br /&gt;
&lt;br /&gt;
In that discussion the initial author of this wiki thought that variables should always be declared. Since then he has changed to not declaring them. In short it is generally a personal preference. In either case, it is the initial authors preference that variables be named according to the following convention, which is used in the examples in this Wiki: &lt;br /&gt;
&lt;br /&gt;
The first letter of the variable name indicates the type of value that the variable is going to hold, as per the following table (based on a table in Tutorial.pdf by Sun) &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Letter&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Meaning&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|-&lt;br /&gt;
|a&lt;br /&gt;
|Structure&lt;br /&gt;
|-&lt;br /&gt;
|b&lt;br /&gt;
|Boolean (TRUE or FALSE)&lt;br /&gt;
|-&lt;br /&gt;
|e&lt;br /&gt;
|Enumeration. This variable can only have one of a limited set of values.&lt;br /&gt;
|-&lt;br /&gt;
|f&lt;br /&gt;
|Float (3.402823 x 1038 to 1.401298 x 10-45. A single variable can take up to four bytes)&amp;lt;br&amp;gt; Double (1.79769313486232 x 10308 to 4.94065645841247 x 10-324. A double variable can take up to eight bytes)&amp;lt;br&amp;gt; Currency (-922337203685477.5808 to +922337203685477.5807 and takes up to eight bytes of memory)&lt;br /&gt;
|-&lt;br /&gt;
|m&lt;br /&gt;
|Array (aka sequence aka matrix)&lt;br /&gt;
|-&lt;br /&gt;
|n&lt;br /&gt;
|Integer (-32768 to 32767.) or&amp;lt;br&amp;gt; Long (-2147483648 and 2147483647).&lt;br /&gt;
|-&lt;br /&gt;
|o&lt;br /&gt;
|Object, service, or interface&lt;br /&gt;
|-&lt;br /&gt;
|s&lt;br /&gt;
|String (A string variable can store up to 65535 Unicode characters).&lt;br /&gt;
|-&lt;br /&gt;
|x&lt;br /&gt;
|Interface, to indicate that only operations of a particular interface of an object are used&lt;br /&gt;
|-&lt;br /&gt;
|v&lt;br /&gt;
|Variant, Any&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Use long descriptive variable names making use of camel case &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|User defined OpenOffice.org Basic variables are not case sensitive. But UNO-API constants are case sensitive.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Convention exceptions to long descriptive names is for index variables where i, j, and k are commonly used, and for when a string is being built-up, where s is commonly used. &lt;br /&gt;
&lt;br /&gt;
Edit sub HelloWorld so that it looks like the following and run it: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub HelloWorld&lt;br /&gt;
dim i as integer &amp;#039;This line is optional&lt;br /&gt;
for i = 0 to 2&lt;br /&gt;
        &amp;#039;These lines are indented for ease of reading only&lt;br /&gt;
        msgbox &amp;quot;Hello World &amp;quot; &amp;amp; i&lt;br /&gt;
next&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
For more information on variables see: [[ using variables]]. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Understanding the OpenOffice.org API=&lt;br /&gt;
This section will start with an example. The remainder of this section aims to give information so that the example can be understood and expanded upon. &lt;br /&gt;
&lt;br /&gt;
Try running the following code with different types of documents being active. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
&amp;#039;basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
&amp;#039;xray.xray thisComponent&lt;br /&gt;
msgbox fnWhichComponent(thisComponent)&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function fnWhichComponent(oDoc) as string&lt;br /&gt;
if HasUnoInterfaces(oDoc, &amp;quot;com.sun.star.lang.XServiceInfo&amp;quot;) then &lt;br /&gt;
   if thisComponent.supportsService (&amp;quot;com.sun.star.text.GenericTextDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Text&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.sheet.SpreadsheetDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Spreadsheet&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.presentation.PresentationDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Presentation&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.drawing.GenericDrawingDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Drawing&amp;quot;&lt;br /&gt;
   else&lt;br /&gt;
      fnWhichComponent = &amp;quot;Oops current document something else&amp;quot;&lt;br /&gt;
   end if&lt;br /&gt;
else&lt;br /&gt;
   fnWhichComponent = &amp;quot;Not a document&amp;quot;&lt;br /&gt;
end if&lt;br /&gt;
End function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subroutine naming convention==&lt;br /&gt;
In the above example the user defined function has a name that starts with the letters &amp;quot;fn&amp;quot;. This is the initial authors convention so that people know that this is a user defined function. Similarly, the initial author uses the convention that user defined subroutines start with the letters &amp;quot;sub&amp;quot;. When learning a language and an API it can be difficult to know what is built-in and what has been defined elsewhere. This document/wiki will use this convention for naming functions and subroutines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Introducing the OpenOffice.org API==&lt;br /&gt;
This section introduces the following terms: &lt;br /&gt;
&lt;br /&gt;
* Interface &lt;br /&gt;
* Module &lt;br /&gt;
* Service &lt;br /&gt;
* Method &lt;br /&gt;
* Property &lt;br /&gt;
&lt;br /&gt;
Understanding the difference between an interface and a service and what a module is, is not essential to being able to write extensions for OpenOffice.org, but it does help interpreting the documentation, and for introspection purposes. You may need to read this section at least twice. &lt;br /&gt;
&lt;br /&gt;
An &amp;#039;&amp;#039;&amp;#039;interface&amp;#039;&amp;#039;&amp;#039; is a &amp;#039;&amp;#039;definition&amp;#039;&amp;#039; of a set of methods (and their arguments) that a service which implements that interface must have. &lt;br /&gt;
&lt;br /&gt;
Interfaces are grouped together in &amp;#039;&amp;#039;&amp;#039;modules&amp;#039;&amp;#039;&amp;#039; for naming purposes. All interfaces (and services) start with the name &amp;quot;com.sun.star&amp;quot; then the name of the module then the name of the interface (or service). &lt;br /&gt;
&lt;br /&gt;
For example most services provide the com.sun.star.beans.XPropertySet interface. This interface is stored in the module &amp;quot;beans&amp;quot; and provides access to the properties of a service. A &amp;#039;&amp;#039;&amp;#039;property&amp;#039;&amp;#039;&amp;#039; is a value where as a &amp;#039;&amp;#039;&amp;#039;method&amp;#039;&amp;#039;&amp;#039; is an action. &lt;br /&gt;
&lt;br /&gt;
An OpenOffice.org object can have many services. &lt;br /&gt;
&lt;br /&gt;
An OpenOffice.org object may have a service, which implements an interface, in which a method description says that another OpenOffice.org object is returned.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Introspection==&lt;br /&gt;
HasUnoInterfaces is an OpenOffice.org Basic function for introspection. See this [[http://www.oooforum.org/forum/viewtopic.phtml?t=7068 link]] for information on introspection in other languages. &lt;br /&gt;
&lt;br /&gt;
HasUnoInterfaces returns true if all of the specified interfaces are available for the specified object. &lt;br /&gt;
&lt;br /&gt;
Most OpenOffice.org objects provide the method supportsService because they have the interface com.sun.star.lang.XServiceInfo. &lt;br /&gt;
&lt;br /&gt;
In the above example, the OpenOffice.org Basic command, &amp;#039;&amp;#039;&amp;#039;HasUnoInterfaces&amp;#039;&amp;#039;&amp;#039; checks that the current document has the interface com.sun.star.lang.XServiceInfo, because if it doesn&amp;#039;t have that interface then it doesn&amp;#039;t have the method supportsService, and a run time error would occur if such an object tried to access its nonexistent method. &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;SupportsService&amp;#039;&amp;#039;&amp;#039; is a method which returns true if the specified service is available. The above examples checks for a service to determine the type of document that is currently active.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==X-Ray tool==&lt;br /&gt;
Using HasUnoInterfaces and supportsService gives information about an object at run time, but checking an object like this would be a nightmare for learning? Thankfully Bernard Marcelly has come to our rescue with the X-Ray tool. The X-Ray tool is available from: [[http://ooomacros.org/dev.php#101416 ooomacros]]. Download the zip file, unzip the document, open the document in OpenOffice.org, follow the instructions for installation and set-up. &lt;br /&gt;
&lt;br /&gt;
Part of the X-Ray tool set-up is to specify a local copy of the OpenOffice.org SDK. Download the OpenOffice.org SDK from and extract it. &lt;br /&gt;
&lt;br /&gt;
In the above example, at the start of the code, there are two commented lines (comments start with an apostrophe): &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039;basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
&amp;#039;xray.xray thisComponent&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Now that you have the X-Ray tool installed, uncomment these lines (remove the apostrophes) and rerun the macro. From version 5 of Xray the command simply becomes xray.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;BasicLibraries&amp;#039;&amp;#039;&amp;#039; is an OpenOffice.org Basic command that returns an object for accessing the OpenOffice.org libraries. The &amp;lt;tt&amp;gt;loadLibrary&amp;lt;/tt&amp;gt; method ensures that the routines in that library are available for use. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;xray.xray&amp;lt;/tt&amp;gt; specifies the xray library and the xray subroutine within that library, thisComponent is the object that is being passed to xray for introspection. &lt;br /&gt;
&lt;br /&gt;
To find the object that you want to work with often requires finding or creating it starting from either StarDesktop or thisComponent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Desktop, documents, and current selection==&lt;br /&gt;
StarDesktop and ThisComponent are OpenOffice.org Basic commands that refer to the application and currently active document respectively. &lt;br /&gt;
&lt;br /&gt;
Unlike Microsoft Office, OpenOffice.org is one application with different components. When running some code it maybe useful to check which component is currently active. The above code demonstrates how that checking process can be done. &lt;br /&gt;
&lt;br /&gt;
The Desktop that StarDesktop refers to is conceptual (historically it actually existed) and can be thought of as the OpenOffice.org application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Creating new documents==&lt;br /&gt;
To create a new text document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/swriter&amp;quot;, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To create a new spreadsheet document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/scalc&amp;quot;, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
An easier approach would be to write a simple function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnNewDoc(sDocType as string)&lt;br /&gt;
fnNewDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/&amp;quot; &amp;amp; sDocType , &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Then creating new documents can be achieved with: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;swriter&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;scalc&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;simpress&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;sdraw&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;smath&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
See [[ loadComponentFromUrl]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==To open a document==&lt;br /&gt;
The following example shows how to open a file. For information on URLs in OpenOffice.org see [[ URL Basics]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sFile = &amp;quot;C:\Documents and Settings\danny\Desktop\MyCalc.sxc&amp;quot; &amp;#039; Windows&lt;br /&gt;
sFile = &amp;quot;/home/danny/Desktop/MyCalc.sxc&amp;quot; &amp;#039; Linux&lt;br /&gt;
sURL = ConvertToURL(sFile)&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(sURL, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Again it may make sense to make this easier by writing a simple function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnOpenDoc(sFile)&lt;br /&gt;
sURL = ConvertToURL(sFile)&lt;br /&gt;
fnOpenDoc = StarDesktop.loadComponentFromURL(sURL, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Examples of calling the function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = fnOpenDoc(&amp;quot;C:\Documents and Settings\danny\Desktop\MyCalc.sxc&amp;quot;) &amp;#039; Windows&lt;br /&gt;
oDoc = fnOpenDoc(&amp;quot;/home/danny/Desktop/MyCalc.sxc&amp;quot;) &amp;#039; Linux&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Current Selection==&lt;br /&gt;
It is common to want to run some code that effects the current selection. &amp;lt;tt&amp;gt;ThisComponent&amp;lt;/tt&amp;gt; has the method &amp;lt;tt&amp;gt;getCurrentSelection&amp;lt;/tt&amp;gt;. Since many different types of objects could possibly be selected it is common to check that the currently selected object has the service that contains the method that we want to apply to the object. &lt;br /&gt;
&lt;br /&gt;
Edit the main subroutine to the following and rerun it on a text document with different selections. (To select more than one block of text hold down the control key). &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
if fnWhichComponent(thisComponent) = &amp;quot;Text&amp;quot; then&lt;br /&gt;
        oCurSelection = thisComponent.getCurrentSelection()&lt;br /&gt;
        &amp;#039;xray.xray oCurSelection&lt;br /&gt;
        if oCurSelection.supportsService(&amp;quot;com.sun.star.text.TextRanges&amp;quot;) then&lt;br /&gt;
                msgbox &amp;quot;There are &amp;quot; &amp;amp; oCurSelection.getCount() &amp;amp; _&lt;br /&gt;
                 &amp;quot; selections in the current text document.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
With nothing selected the number of selections is one - the insertion point, with one block of text selected the count is still one, but with two blocks of text the count is three - the insertion point and the two blocks of selected text. &lt;br /&gt;
&lt;br /&gt;
Exercise 1: Modify the above code so that it works on selected cell ranges in a spreadsheet. &lt;br /&gt;
&lt;br /&gt;
Question1: For two blocks of cells selected, what would be the count for the number of selections? &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Properties==&lt;br /&gt;
Uncomment &amp;lt;tt&amp;gt;&amp;#039;xray.xray oCurSelection&amp;lt;/tt&amp;gt; so that xray runs, to see that the object that &amp;lt;tt&amp;gt;oCurSelection&amp;lt;/tt&amp;gt; points to has a &amp;quot;property&amp;quot; called &amp;lt;tt&amp;gt;Count&amp;lt;/tt&amp;gt; with a description of &amp;quot;pseudo-prop, read only&amp;quot;. It is possible in OpenOffice.org Basic to write &amp;lt;tt&amp;gt;oCurSelection.count&amp;lt;/tt&amp;gt;, but as this is not possible in all other languages accessing the OpenOffice.org API, this Wiki will try to always use the method approach. (I say try because I have not been in the habit of doing this and sometimes I may forget). &lt;br /&gt;
&lt;br /&gt;
This next example demonstrates changing a property value for the current selections. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
if fnWhichComponent(thisComponent) = &amp;quot;Text&amp;quot; then&lt;br /&gt;
   oCurSelection = thisComponent.getCurrentSelection()&lt;br /&gt;
   if oCurSelection.supportsService(&amp;quot;com.sun.star.text.TextRanges&amp;quot;) then&lt;br /&gt;
      nCount = oCurSelection.Count&lt;br /&gt;
      &amp;#039;xray.xray oCurSelection.getByIndex(0)&lt;br /&gt;
      &amp;#039;Warning: The insertion point will have the same action applied twice&lt;br /&gt;
      &amp;#039;in this case it doesn&amp;#039;t matter, but in others it might.&lt;br /&gt;
      for i = 0 to nCount - 1&lt;br /&gt;
         oCurSelection.getByIndex(i).setPropertyValue(&amp;quot;CharStyleName&amp;quot;, &amp;quot;Strong Emphasis&amp;quot;)&lt;br /&gt;
      next&lt;br /&gt;
   end if&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
In OpenOffice.org Basic it is possible to shorten the assignment line to: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oCurSelection(i).CharStyleName = &amp;quot;Strong Emphasis&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This wiki will try to use the full methods for both indexing and assigning properties. The rationale is that this makes converting the code to other languages easier and also helps the learner to understand what is happening (again I have not been in the habit of doing this so some examples may slip past me). &lt;br /&gt;
&lt;br /&gt;
Exercise 2: Rewrite the above code so that the warning can be removed. &lt;br /&gt;
&lt;br /&gt;
See [[ Current selection]]. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Iterative Access to Subordinate Objects (Enumeration access)=&lt;br /&gt;
Sometimes to access the desired object an enumeration is required. For example paragraphs, within a document or within a selection. &lt;br /&gt;
&lt;br /&gt;
When a Writer document is active and some text is selected, both &amp;lt;tt&amp;gt;thisDocument.getText()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;thisComponent.getCurrentSelection().getByIndex(i)&amp;lt;/tt&amp;gt; have the service: com.sun.star.text.TextRange which has the interface: com.sun.star.container.XContentEnumerationAccess, it is possible to create an enumeration of the paragraphs for the current document or for a particular selection. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; Create enumeration object&lt;br /&gt;
oTextElementEnum = thisComponent.getText().createEnumeration()&lt;br /&gt;
&amp;#039;or thisComponent.getCurrentSelection().getByIndex(i).createEnumeration()&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; loop over all text elements&lt;br /&gt;
while oTextElementEnum.hasMoreElements()&lt;br /&gt;
        oTextElement = oTextElementEnum.nextElement&lt;br /&gt;
        if oTextElement.supportsService(&amp;quot;com.sun.star.text.TextTable&amp;quot;) then&lt;br /&gt;
                MsgBox &amp;quot;The current block contains a table.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
        if oTextElement.supportsService(&amp;quot;com.sun.star.text.Paragraph&amp;quot;) then&lt;br /&gt;
                MsgBox &amp;quot;The current block contains a paragraph.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
wend&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Exercise 3: Extend the above example to display in a message box all text portions that are bold. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Named access=&lt;br /&gt;
Some objects provide named access to a particular type of subordinate object, some others indexed access, and some both named and indexed access. &lt;br /&gt;
&lt;br /&gt;
For example if the current document in OpenOffice.org is a spreadsheet then to access a particular sheet can be done by index access: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oSheet = thisComponent.getSheets.getByIndex(0)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
or named access: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oSheet = thisComponent.getSheets.getByName(&amp;quot;Sheet1&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To check if an object with a particular name already exists use &amp;lt;tt&amp;gt;hasByName&amp;lt;/tt&amp;gt;, for example: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
if thisComponent.getSheets.hasByName(&amp;quot;Sheet1&amp;quot;) then&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To loop through all the available object names can be done like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
mNames = thisComponent.getSheets.getElementnames&lt;br /&gt;
for i = lbound(mNames) to ubound(mNames)&lt;br /&gt;
        msgbox mNames(i)&lt;br /&gt;
next&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Some named subordinate objects also provide the interface:  com.sun.star.container.XNameContainer. This interface defines that such objects should have the following methods: &amp;lt;tt&amp;gt;insertByName&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;replaceByname&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;removeByName&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
E.g. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
thisComponent.getSheets.insertByName(&amp;quot;NewSheet&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Create new objects=&lt;br /&gt;
Some objects have services which implement interfaces to provide specific methods for creating a particular type of object. &lt;br /&gt;
&lt;br /&gt;
For example if the current document is a Writer document then &amp;lt;tt&amp;gt;thisComponent.getText&amp;lt;/tt&amp;gt; is an object that provides the service com.sun.star.text.Text which implements the interface  com.sun.star.text.XSimpleText which defines the methods &amp;lt;tt&amp;gt;createTextCursor&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;createTextCursorByRange&amp;lt;/tt&amp;gt;. Both of these methods create a text cursor for accessing the text of the document. These cursors are quite independent of the view cursor . The view cursor is visible on the screen and is manipulated by the user (and can be manipulated by program control), where as a text cursor is not visible on the screen and is solely used by program control. The following code snippet demonstrates creating a new text cursor, such that it starts at the same location as the viewCursor and is then moved independent of the view cursor. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oVC = thisComponent.getCurrentController.getViewCursor&lt;br /&gt;
oCursor = oVC.getText.createTextCursorByRange(oVC)&lt;br /&gt;
oCursor.gotoStartOfSentence(false)&lt;br /&gt;
oCursor.gotoEndOfSentence(true)&lt;br /&gt;
msgbox oCursor.getString&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Some objects are context dependent and get created using the method &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt; which is defined in the interface com.sun.star.lang.XMultiServiceFactory. For example to add a rectangle to the first page of a drawing document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
dim aPoint as new com.sun.star.awt.Point&lt;br /&gt;
dim aSize as new com.sun.star.awt.Size&lt;br /&gt;
 &lt;br /&gt;
aPoint.x = 1000&lt;br /&gt;
aPoint.y = 1000&lt;br /&gt;
 &lt;br /&gt;
aSize.Width = 10000&lt;br /&gt;
aSize.Height = 10000&lt;br /&gt;
 &lt;br /&gt;
oRectangleShape = thisComponent.createInstance(&amp;quot;com.sun.star.drawing.RectangleShape&amp;quot;)&lt;br /&gt;
oRectangleShape.Size = aSize&lt;br /&gt;
oRectangleShape.Position = aPoint&lt;br /&gt;
 &lt;br /&gt;
thisComponent.getDrawPages.getByIndex(0).add(oRectangleShape)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example also uses UNO structs see below for more information on UNO stucts. &lt;br /&gt;
&lt;br /&gt;
Some objects are context independent to create these objects use the OpenOffice.org Basic command createUnoService. For example to create the equivalent to StarDesktop: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDesktop = createUnoService(&amp;quot;com.sun.star.frame.Desktop&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The process that I use to determine how to access or create an object is as follows: &lt;br /&gt;
&lt;br /&gt;
Does the object already exist if so I should be able to access it from something like &amp;lt;tt&amp;gt;thisComponent&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Will the new object belong to another object, if so does the owner have a specific method for creating the object, if so use it. &lt;br /&gt;
&lt;br /&gt;
The new object will belong to another object, but that object doesn&amp;#039;t provide a specific method for creating it, but does provide &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt;. If the object doesn&amp;#039;t provide &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt; are you sure you are using the correct object, or is it context independent. &lt;br /&gt;
&lt;br /&gt;
I have found working out how to create an object to be quite difficult with existing documentation so I hope that this document/wiki will eventually make this clear. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==UNO structs==&lt;br /&gt;
UNO structures can be declared using the OpenOffice.org Basic command &amp;lt;tt&amp;gt;dim&amp;lt;/tt&amp;gt;: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
dim aPoint as new com.sun.star.awt.Point&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Or by using the OpenOffice.org Basic command &amp;lt;tt&amp;gt;createUnoStruct&amp;lt;/tt&amp;gt;: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
aPoint = createUnoStruct(&amp;quot;com.sun.star.awt.Point&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|When declaring UNO structs case is important. Note that everything upto the name of the struct is lowercase, and that the name of the struct is in TitleCase.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Creating Listeners and Handlers==&lt;br /&gt;
Through the user interface it is possible to assign macros to some events: &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org versions 1.1.x: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Configure… &amp;gt; Events&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org versions 1.9.x and above: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Customize… &amp;gt; Events&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
It is also possible to assign macros to a wider range of events using the OpenOffice.org Basic command CreateUnoListener. This same command is used for creating both listeners and handlers. A listener checks for an event and always allows other listeners to respond to the event as well. A handler listens for an event, and can optionally consume the event so that other listeners don&amp;#039;t get to act on it. &lt;br /&gt;
&lt;br /&gt;
The following example creates a keyHandler: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
global IannzExampleKeyHandler&lt;br /&gt;
 &lt;br /&gt;
sub SetupKeyHandler&lt;br /&gt;
oController = thisComponent.currentController&lt;br /&gt;
IannzExampleKeyHandler = CreateUnoListener(&amp;quot;KeyHandler_&amp;quot;,&amp;quot;com.sun.star.awt.XKeyHandler&amp;quot;)&lt;br /&gt;
oController.addKeyHandler(IannzExampleKeyHandler) &amp;#039; Register the listener&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
sub RemoveKeyHandler&lt;br /&gt;
thisComponent.currentController.removeKeyHandler(IannzExampleKeyHandler)&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
sub KeyHandler_disposing&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function KeyHandler_keyReleased(oKeyEvent as new com.sun.star.awt.KeyHandler) as boolean&lt;br /&gt;
        KeyHandler_keyReleased = False    &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function KeyHandler_keyPressed(oKeyEvent as new com.sun.star.awt.KeyHandler) as boolean&lt;br /&gt;
KeyHandler_keyPressed = false   &amp;#039;Let other listeners handle the event&lt;br /&gt;
if oKeyEvent.modifiers = com.sun.star.awt.KeyModifier.MOD2 then &amp;#039;Control key was pressed&lt;br /&gt;
        if oKeyEvent.keyCode = com.sun.star.awt.Key.Q then&lt;br /&gt;
                msgbox &amp;quot;Alt + Q was pressed&amp;quot;&lt;br /&gt;
                KeyHandler_keyPressed = true    &amp;#039;Don&amp;#039;t let other listeners process this event&lt;br /&gt;
        end if&lt;br /&gt;
end if&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
A variable declared as global keeps its value even after the macro exits. In this case we want to be able to use this variable later to remove the handler. As variables declared globally could be used in other libraries to try and avoid conflict I start all my global variables with Iannz my registered name for the OpenOffice.org web site. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;sub SetupKeyHandler&amp;lt;/tt&amp;gt; sets up the handler. The first parameter to CreateUnoListener is the staring name for the methods that will be called when that type of event occurs in this example .&amp;lt;tt&amp;gt;&amp;quot;KeyHandler_&amp;quot;&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
The second parameter is the name of the interface for the listener or handler, &amp;quot;com.sun.star.awt.XKeyHandler&amp;quot;. The name is case sensitive, everything up to and including the module name is always lowercase, the name of the interface always starts with &amp;quot;X&amp;quot; and the remainder is in TitleCase. &lt;br /&gt;
&lt;br /&gt;
Use the SDK to find out what methods the interface must supply. You must supply routines for all of these methods even if you don&amp;#039;t intend to use them. You also need to supply a disposing method. The names of these routines start with the string given in the first parameter to CreateUnoListener , in this example &amp;lt;tt&amp;gt;&amp;quot;KeyHandler_&amp;quot;&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Thus in the example there is &amp;lt;tt&amp;gt;KeyHandler_disposing&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;KeyHandler_keyReleased&amp;lt;/tt&amp;gt; which don&amp;#039;t actually do anything but are required, and &amp;lt;tt&amp;gt;KeyHandler_keyPressed&amp;lt;/tt&amp;gt; which actually does the job. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;sub RemoveKeyHandler&amp;lt;/tt&amp;gt; demonstrates how to remove the handler.&lt;br /&gt;
&lt;br /&gt;
=OpenOffice.org constants=&lt;br /&gt;
The above example uses OpenOffice.org constants. &lt;br /&gt;
&lt;br /&gt;
E.g. com.sun.star.awt.KeyModifier.MOD2&lt;br /&gt;
&lt;br /&gt;
OpenOffice.org constants are case sensitive. Everything up to and including the module name is always lowercase. The constant group is in TitleCase. The actual constant name is always UPPERCASE. &lt;br /&gt;
&lt;br /&gt;
Programmers not using OpenOffice.org Basic may not have access to these constants. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Using the recorder=&lt;br /&gt;
See [[ The OpenOffice.org recorder and UNO dispatch calls]] section for a discussion on recording UNO Dispatch commands versus writing API calls.&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Extensions_development_basic&amp;diff=7460</id>
		<title>Extensions development basic</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Extensions_development_basic&amp;diff=7460"/>
		<updated>2006-04-04T05:43:16Z</updated>

		<summary type="html">&lt;p&gt;Iannz: /* Create new objects */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;Getting started tutorial&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Before we can access the OpenOffice.org Basic Integrated Development Environment (IDE), to write some code, a decision needs to be made about where the code is to be stored. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Where do I write the code?=&lt;br /&gt;
OpenOffice.org Basic code is stored in modules within libraries. A library can be: &lt;br /&gt;
&lt;br /&gt;
*Shared (for a network install - OOo Macros &amp;amp; Dialogs) &lt;br /&gt;
*Just for the current user (My Macros &amp;amp; Dialogs) &lt;br /&gt;
*Within a document or template, so that its code is only available when that document is open.Within a document or template, so that its code is only available when that document is open. &lt;br /&gt;
Libraries not stored in a document or template (that is libraries that are shared or for the current user) are referred to as &amp;#039;&amp;#039;&amp;#039;OpenOffice.org libraries&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
To determine the actual folders that contain the OpenOffice.org libraries see:&amp;lt;br&amp;gt; &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Options… &amp;gt; OpenOffice.org &amp;gt; Paths &amp;gt; BASIC&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|Do not copy or move libraries using operating system commands. Use the macro organizer or package manager instead.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Modules within libraries have a maximum size of 64kb. A library can contain up to 16,000 modules. &lt;br /&gt;
&lt;br /&gt;
For more information see online help for: Modules and Libraries. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Accessing the IDE=&lt;br /&gt;
To access the IDE for the first time: &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org 1.1.x: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Macro… &amp;gt;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org 1.9.x and above: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Organize macros &amp;gt; OpenOffice.org Basic… &amp;gt;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
To get started we will use Module1 in the Standard library which is stored for the current user only: &lt;br /&gt;
&lt;br /&gt;
Type a name for the new macro: &amp;#039;&amp;#039;&amp;#039;HelloWorld&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
In the macro from listbox select &amp;#039;&amp;#039;&amp;#039;Standard&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Click &amp;#039;&amp;#039;&amp;#039;New&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
You should now see something like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
REM  *****  BASIC  *****&lt;br /&gt;
 &lt;br /&gt;
Sub Main&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
 &lt;br /&gt;
Sub HelloWorld&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The cursor will be positioned at the start of the &amp;lt;tt&amp;gt;Sub HelloWorld&amp;lt;/tt&amp;gt; line. &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|Now that while the IDE is running it can be accessed from the OpenOffice.org Window menu, or the task panel provided by the operating system.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Entering the code=&lt;br /&gt;
Select and delete: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
REM  *****  BASIC  *****&lt;br /&gt;
 &lt;br /&gt;
Sub Main&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Below the line &amp;quot;Sub HelloWorld&amp;quot; type [[ msgbox]]&amp;lt;tt&amp;gt; &amp;quot;Hello World!&amp;quot;&amp;lt;/tt&amp;gt;, so that the editor looks like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Sub HelloWorld&lt;br /&gt;
msgbox &amp;quot;Hello World!&amp;quot;&lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Notes:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|The IDE does not provide code completion or help with command syntax as you type, but to get help on a Basic command position the cursor in the command and press F1.&amp;lt;br&amp;gt; OpenOffice.org Basic commands are not case sensitive. Thus msgbox, MSGBOX and Msgbox will all work.&amp;lt;br&amp;gt; Strings are enclosed in double quotes.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Running the code=&lt;br /&gt;
There are several ways of running the Basic code, these include: &lt;br /&gt;
&lt;br /&gt;
Directly from the IDE. There is a run button on the macro bar (by default the third control on the second toolbar). This will run the first macro in the current module. &lt;br /&gt;
&lt;br /&gt;
From the tools menu: (Version 1.1.x) &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Macro…&amp;#039;&amp;#039;&amp;#039;; (Version 1.9.x and above) &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macro &amp;gt; Run Macro…&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a [[ key press]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a [[ menu entry]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a toolbar button. &lt;br /&gt;
&lt;br /&gt;
Creating a [[ control in a document]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to an event. &lt;br /&gt;
&lt;br /&gt;
For now try running the &amp;quot;HelloWorld&amp;quot; subroutine by clicking the &amp;#039;&amp;#039;&amp;#039;Run&amp;#039;&amp;#039;&amp;#039; button. A small dialog titled &amp;quot;soffice&amp;quot; with the text &amp;quot;Hello World!&amp;quot; and an OK button should be displayed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Saving the code=&lt;br /&gt;
The code gets automatically saved whenever the container for the code gets saved. Thus, if the code is in an OpenOffice.org library (shared or users) then it gets automatically saved when OpenOffice.org exits. If the code is in a library which is part of a document it gets saved whenever the document is saved. &lt;br /&gt;
&lt;br /&gt;
On the Standard toolbar (by default the top toolbar) in the IDE there is a save button. If the code is in a document or template then clicking this button saves the entire document or template. If the code is in an OpenOffice.org library then just the current library gets saved. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Variables=&lt;br /&gt;
It is possible to force variable declaration with &amp;lt;tt&amp;gt;Option Explicit&amp;lt;/tt&amp;gt; at the top of the module. For a discussion on whether to declare variables or not see: [[http://www.oooforum.org/forum/viewtopic.phtml?t=5845 this discussion]]. &lt;br /&gt;
&lt;br /&gt;
In that discussion the initial author of this wiki thought that variables should always be declared. Since then he has changed to not declaring them. In short it is generally a personal preference. In either case, it is the initial authors preference that variables be named according to the following convention, which is used in the examples in this Wiki: &lt;br /&gt;
&lt;br /&gt;
The first letter of the variable name indicates the type of value that the variable is going to hold, as per the following table (based on a table in Tutorial.pdf by Sun) &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Letter&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Meaning&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|-&lt;br /&gt;
|a&lt;br /&gt;
|Structure&lt;br /&gt;
|-&lt;br /&gt;
|b&lt;br /&gt;
|Boolean (TRUE or FALSE)&lt;br /&gt;
|-&lt;br /&gt;
|e&lt;br /&gt;
|Enumeration. This variable can only have one of a limited set of values.&lt;br /&gt;
|-&lt;br /&gt;
|f&lt;br /&gt;
|Float (3.402823 x 1038 to 1.401298 x 10-45. A single variable can take up to four bytes)&amp;lt;br&amp;gt; Double (1.79769313486232 x 10308 to 4.94065645841247 x 10-324. A double variable can take up to eight bytes)&amp;lt;br&amp;gt; Currency (-922337203685477.5808 to +922337203685477.5807 and takes up to eight bytes of memory)&lt;br /&gt;
|-&lt;br /&gt;
|m&lt;br /&gt;
|Array (aka sequence aka matrix)&lt;br /&gt;
|-&lt;br /&gt;
|n&lt;br /&gt;
|Integer (-32768 to 32767.) or&amp;lt;br&amp;gt; Long (-2147483648 and 2147483647).&lt;br /&gt;
|-&lt;br /&gt;
|o&lt;br /&gt;
|Object, service, or interface&lt;br /&gt;
|-&lt;br /&gt;
|s&lt;br /&gt;
|String (A string variable can store up to 65535 Unicode characters).&lt;br /&gt;
|-&lt;br /&gt;
|x&lt;br /&gt;
|Interface, to indicate that only operations of a particular interface of an object are used&lt;br /&gt;
|-&lt;br /&gt;
|v&lt;br /&gt;
|Variant, Any&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Use long descriptive variable names making use of camel case &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|User defined OpenOffice.org Basic variables are not case sensitive. But UNO-API constants are case sensitive.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Convention exceptions to long descriptive names is for index variables where i, j, and k are commonly used, and for when a string is being built-up, where s is commonly used. &lt;br /&gt;
&lt;br /&gt;
Edit sub HelloWorld so that it looks like the following and run it: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub HelloWorld&lt;br /&gt;
dim i as integer &amp;#039;This line is optional&lt;br /&gt;
for i = 0 to 2&lt;br /&gt;
        &amp;#039;These lines are indented for ease of reading only&lt;br /&gt;
        msgbox &amp;quot;Hello World &amp;quot; &amp;amp; i&lt;br /&gt;
next&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
For more information on variables see: [[ using variables]]. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Understanding the OpenOffice.org API=&lt;br /&gt;
This section will start with an example. The remainder of this section aims to give information so that the example can be understood and expanded upon. &lt;br /&gt;
&lt;br /&gt;
Try running the following code with different types of documents being active. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
&amp;#039;basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
&amp;#039;xray.xray thisComponent&lt;br /&gt;
msgbox fnWhichComponent(thisComponent)&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function fnWhichComponent(oDoc) as string&lt;br /&gt;
if HasUnoInterfaces(oDoc, &amp;quot;com.sun.star.lang.XServiceInfo&amp;quot;) then &lt;br /&gt;
   if thisComponent.supportsService (&amp;quot;com.sun.star.text.GenericTextDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Text&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.sheet.SpreadsheetDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Spreadsheet&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.presentation.PresentationDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Presentation&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.drawing.GenericDrawingDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Drawing&amp;quot;&lt;br /&gt;
   else&lt;br /&gt;
      fnWhichComponent = &amp;quot;Oops current document something else&amp;quot;&lt;br /&gt;
   end if&lt;br /&gt;
else&lt;br /&gt;
   fnWhichComponent = &amp;quot;Not a document&amp;quot;&lt;br /&gt;
end if&lt;br /&gt;
End function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subroutine naming convention==&lt;br /&gt;
In the above example the user defined function has a name that starts with the letters &amp;quot;fn&amp;quot;. This is the initial authors convention so that people know that this is a user defined function. Similarly, the initial author uses the convention that user defined subroutines start with the letters &amp;quot;sub&amp;quot;. When learning a language and an API it can be difficult to know what is built-in and what has been defined elsewhere. This document/wiki will use this convention for naming functions and subroutines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Introducing the OpenOffice.org API==&lt;br /&gt;
This section introduces the following terms: &lt;br /&gt;
&lt;br /&gt;
* Interface &lt;br /&gt;
* Module &lt;br /&gt;
* Service &lt;br /&gt;
* Method &lt;br /&gt;
* Property &lt;br /&gt;
&lt;br /&gt;
Understanding the difference between an interface and a service and what a module is, is not essential to being able to write extensions for OpenOffice.org, but it does help interpreting the documentation, and for introspection purposes. You may need to read this section at least twice. &lt;br /&gt;
&lt;br /&gt;
An &amp;#039;&amp;#039;&amp;#039;interface&amp;#039;&amp;#039;&amp;#039; is a &amp;#039;&amp;#039;definition&amp;#039;&amp;#039; of a set of methods (and their arguments) that a service which implements that interface must have. &lt;br /&gt;
&lt;br /&gt;
Interfaces are grouped together in &amp;#039;&amp;#039;&amp;#039;modules&amp;#039;&amp;#039;&amp;#039; for naming purposes. All interfaces (and services) start with the name &amp;quot;com.sun.star&amp;quot; then the name of the module then the name of the interface (or service). &lt;br /&gt;
&lt;br /&gt;
For example most services provide the com.sun.star.beans.XPropertySet interface. This interface is stored in the module &amp;quot;beans&amp;quot; and provides access to the properties of a service. A &amp;#039;&amp;#039;&amp;#039;property&amp;#039;&amp;#039;&amp;#039; is a value where as a &amp;#039;&amp;#039;&amp;#039;method&amp;#039;&amp;#039;&amp;#039; is an action. &lt;br /&gt;
&lt;br /&gt;
An OpenOffice.org object can have many services. &lt;br /&gt;
&lt;br /&gt;
An OpenOffice.org object may have a service, which implements an interface, in which a method description says that another OpenOffice.org object is returned.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Introspection==&lt;br /&gt;
HasUnoInterfaces is an OpenOffice.org Basic function for introspection. See this [[http://www.oooforum.org/forum/viewtopic.phtml?t=7068 link]] for information on introspection in other languages. &lt;br /&gt;
&lt;br /&gt;
HasUnoInterfaces returns true if all of the specified interfaces are available for the specified object. &lt;br /&gt;
&lt;br /&gt;
Most OpenOffice.org objects provide the method supportsService because they have the interface com.sun.star.lang.XServiceInfo. &lt;br /&gt;
&lt;br /&gt;
In the above example, the OpenOffice.org Basic command, &amp;#039;&amp;#039;&amp;#039;HasUnoInterfaces&amp;#039;&amp;#039;&amp;#039; checks that the current document has the interface com.sun.star.lang.XServiceInfo, because if it doesn&amp;#039;t have that interface then it doesn&amp;#039;t have the method supportsService, and a run time error would occur if such an object tried to access its nonexistent method. &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;SupportsService&amp;#039;&amp;#039;&amp;#039; is a method which returns true if the specified service is available. The above examples checks for a service to determine the type of document that is currently active.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==X-Ray tool==&lt;br /&gt;
Using HasUnoInterfaces and supportsService gives information about an object at run time, but checking an object like this would be a nightmare for learning? Thankfully Bernard Marcelly has come to our rescue with the X-Ray tool. The X-Ray tool is available from: [[http://ooomacros.org/dev.php#101416 ooomacros]]. Download the zip file, unzip the document, open the document in OpenOffice.org, follow the instructions for installation and set-up. &lt;br /&gt;
&lt;br /&gt;
Part of the X-Ray tool set-up is to specify a local copy of the OpenOffice.org SDK. Download the OpenOffice.org SDK from and extract it. &lt;br /&gt;
&lt;br /&gt;
In the above example, at the start of the code, there are two commented lines (comments start with an apostrophe): &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039;basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
&amp;#039;xray.xray thisComponent&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Now that you have the X-Ray tool installed, uncomment these lines (remove the apostrophes) and rerun the macro. From version 5 of Xray the command simply becomes xray.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;BasicLibraries&amp;#039;&amp;#039;&amp;#039; is an OpenOffice.org Basic command that returns an object for accessing the OpenOffice.org libraries. The &amp;lt;tt&amp;gt;loadLibrary&amp;lt;/tt&amp;gt; method ensures that the routines in that library are available for use. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;xray.xray&amp;lt;/tt&amp;gt; specifies the xray library and the xray subroutine within that library, thisComponent is the object that is being passed to xray for introspection. &lt;br /&gt;
&lt;br /&gt;
To find the object that you want to work with often requires finding or creating it starting from either StarDesktop or thisComponent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Desktop, documents, and current selection==&lt;br /&gt;
StarDesktop and ThisComponent are OpenOffice.org Basic commands that refer to the application and currently active document respectively. &lt;br /&gt;
&lt;br /&gt;
Unlike Microsoft Office, OpenOffice.org is one application with different components. When running some code it maybe useful to check which component is currently active. The above code demonstrates how that checking process can be done. &lt;br /&gt;
&lt;br /&gt;
The Desktop that StarDesktop refers to is conceptual (historically it actually existed) and can be thought of as the OpenOffice.org application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Creating new documents==&lt;br /&gt;
To create a new text document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/swriter&amp;quot;, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To create a new spreadsheet document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/scalc&amp;quot;, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
An easier approach would be to write a simple function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnNewDoc(sDocType as string)&lt;br /&gt;
fnNewDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/&amp;quot; &amp;amp; sDocType , &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Then creating new documents can be achieved with: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;swriter&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;scalc&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;simpress&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;sdraw&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;smath&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
See [[ loadComponentFromUrl]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==To open a document==&lt;br /&gt;
The following example shows how to open a file. For information on URLs in OpenOffice.org see [[ URL Basics]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sFile = &amp;quot;C:\Documents and Settings\danny\Desktop\MyCalc.sxc&amp;quot; &amp;#039; Windows&lt;br /&gt;
sFile = &amp;quot;/home/danny/Desktop/MyCalc.sxc&amp;quot; &amp;#039; Linux&lt;br /&gt;
sURL = ConvertToURL(sFile)&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(sURL, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Again it may make sense to make this easier by writing a simple function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnOpenDoc(sFile)&lt;br /&gt;
sURL = ConvertToURL(sFile)&lt;br /&gt;
fnOpenDoc = StarDesktop.loadComponentFromURL(sURL, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Examples of calling the function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = fnOpenDoc(&amp;quot;C:\Documents and Settings\danny\Desktop\MyCalc.sxc&amp;quot;) &amp;#039; Windows&lt;br /&gt;
oDoc = fnOpenDoc(&amp;quot;/home/danny/Desktop/MyCalc.sxc&amp;quot;) &amp;#039; Linux&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Current Selection==&lt;br /&gt;
It is common to want to run some code that effects the current selection. &amp;lt;tt&amp;gt;ThisComponent&amp;lt;/tt&amp;gt; has the method &amp;lt;tt&amp;gt;getCurrentSelection&amp;lt;/tt&amp;gt;. Since many different types of objects could possibly be selected it is common to check that the currently selected object has the service that contains the method that we want to apply to the object. &lt;br /&gt;
&lt;br /&gt;
Edit the main subroutine to the following and rerun it on a text document with different selections. (To select more than one block of text hold down the control key). &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
if fnWhichComponent(thisComponent) = &amp;quot;Text&amp;quot; then&lt;br /&gt;
        oCurSelection = thisComponent.getCurrentSelection()&lt;br /&gt;
        &amp;#039;xray.xray oCurSelection&lt;br /&gt;
        if oCurSelection.supportsService(&amp;quot;com.sun.star.text.TextRanges&amp;quot;) then&lt;br /&gt;
                msgbox &amp;quot;There are &amp;quot; &amp;amp; oCurSelection.getCount() &amp;amp; _&lt;br /&gt;
                 &amp;quot; selections in the current text document.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
With nothing selected the number of selections is one - the insertion point, with one block of text selected the count is still one, but with two blocks of text the count is three - the insertion point and the two blocks of selected text. &lt;br /&gt;
&lt;br /&gt;
Exercise 1: Modify the above code so that it works on selected cell ranges in a spreadsheet. &lt;br /&gt;
&lt;br /&gt;
Question1: For two blocks of cells selected, what would be the count for the number of selections? &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Properties==&lt;br /&gt;
Uncomment &amp;lt;tt&amp;gt;&amp;#039;xray.xray oCurSelection&amp;lt;/tt&amp;gt; so that xray runs, to see that the object that &amp;lt;tt&amp;gt;oCurSelection&amp;lt;/tt&amp;gt; points to has a &amp;quot;property&amp;quot; called &amp;lt;tt&amp;gt;Count&amp;lt;/tt&amp;gt; with a description of &amp;quot;pseudo-prop, read only&amp;quot;. It is possible in OpenOffice.org Basic to write &amp;lt;tt&amp;gt;oCurSelection.count&amp;lt;/tt&amp;gt;, but as this is not possible in all other languages accessing the OpenOffice.org API, this Wiki will try to always use the method approach. (I say try because I have not been in the habit of doing this and sometimes I may forget). &lt;br /&gt;
&lt;br /&gt;
This next example demonstrates changing a property value for the current selections. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
if fnWhichComponent(thisComponent) = &amp;quot;Text&amp;quot; then&lt;br /&gt;
   oCurSelection = thisComponent.getCurrentSelection()&lt;br /&gt;
   if oCurSelection.supportsService(&amp;quot;com.sun.star.text.TextRanges&amp;quot;) then&lt;br /&gt;
      nCount = oCurSelection.Count&lt;br /&gt;
      &amp;#039;xray.xray oCurSelection.getByIndex(0)&lt;br /&gt;
      &amp;#039;Warning: The insertion point will have the same action applied twice&lt;br /&gt;
      &amp;#039;in this case it doesn&amp;#039;t matter, but in others it might.&lt;br /&gt;
      for i = 0 to nCount - 1&lt;br /&gt;
         oCurSelection.getByIndex(i).setPropertyValue(&amp;quot;CharStyleName&amp;quot;, &amp;quot;Strong Emphasis&amp;quot;)&lt;br /&gt;
      next&lt;br /&gt;
   end if&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
In OpenOffice.org Basic it is possible to shorten the assignment line to: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oCurSelection(i).CharStyleName = &amp;quot;Strong Emphasis&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This wiki will try to use the full methods for both indexing and assigning properties. The rationale is that this makes converting the code to other languages easier and also helps the learner to understand what is happening (again I have not been in the habit of doing this so some examples may slip past me). &lt;br /&gt;
&lt;br /&gt;
Exercise 2: Rewrite the above code so that the warning can be removed. &lt;br /&gt;
&lt;br /&gt;
See [[ Current selection]]. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Iterative Access to Subordinate Objects (Enumeration access)=&lt;br /&gt;
Sometimes to access the desired object an enumeration is required. For example paragraphs, within a document or within a selection. &lt;br /&gt;
&lt;br /&gt;
When a Writer document is active and some text is selected, both &amp;lt;tt&amp;gt;thisDocument.getText()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;thisComponent.getCurrentSelection().getByIndex(i)&amp;lt;/tt&amp;gt; have the service: com.sun.star.text.TextRange which has the interface: com.sun.star.container.XContentEnumerationAccess, it is possible to create an enumeration of the paragraphs for the current document or for a particular selection. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; Create enumeration object&lt;br /&gt;
oTextElementEnum = thisComponent.getText().createEnumeration()&lt;br /&gt;
&amp;#039;or thisComponent.getCurrentSelection().getByIndex(i).createEnumeration()&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; loop over all text elements&lt;br /&gt;
while oTextElementEnum.hasMoreElements()&lt;br /&gt;
        oTextElement = oTextElementEnum.nextElement&lt;br /&gt;
        if oTextElement.supportsService(&amp;quot;com.sun.star.text.TextTable&amp;quot;) then&lt;br /&gt;
                MsgBox &amp;quot;The current block contains a table.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
        if oTextElement.supportsService(&amp;quot;com.sun.star.text.Paragraph&amp;quot;) then&lt;br /&gt;
                MsgBox &amp;quot;The current block contains a paragraph.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
wend&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Exercise 3: Extend the above example to display in a message box all text portions that are bold. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Named access=&lt;br /&gt;
Some objects provide named access to a particular type of subordinate object, some others indexed access, and some both named and indexed access. &lt;br /&gt;
&lt;br /&gt;
For example if the current document in OpenOffice.org is a spreadsheet then to access a particular sheet can be done by index access: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oSheet = thisComponent.getSheets.getByIndex(0)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
or named access: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oSheet = thisComponent.getSheets.getByName(&amp;quot;Sheet1&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To check if an object with a particular name already exists use &amp;lt;tt&amp;gt;hasByName&amp;lt;/tt&amp;gt;, for example: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
if thisComponent.getSheets.hasByName(&amp;quot;Sheet1&amp;quot;) then&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To loop through all the available object names can be done like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
mNames = thisComponent.getSheets.getElementnames&lt;br /&gt;
for i = lbound(mNames) to ubound(mNames)&lt;br /&gt;
        msgbox mNames(i)&lt;br /&gt;
next&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Some named subordinate objects also provide the interface:  com.sun.star.container.XNameContainer. This interface defines that such objects should have the following methods: &amp;lt;tt&amp;gt;insertByName&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;replaceByname&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;removeByName&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
E.g. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
thisComponent.getSheets.insertByName(&amp;quot;NewSheet&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Create new objects=&lt;br /&gt;
Some objects have services which implement interfaces to provide specific methods for creating a particular type of object. &lt;br /&gt;
&lt;br /&gt;
For example if the current document is a Writer document then &amp;lt;tt&amp;gt;thisComponent.getText&amp;lt;/tt&amp;gt; is an object that provides the service com.sun.star.text.Text which implements the interface  com.sun.star.text.XSimpleText which defines the methods &amp;lt;tt&amp;gt;createTextCursor&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;createTextCursorByRange&amp;lt;/tt&amp;gt;. Both of these methods create a text cursor for accessing the text of the document. These cursors are quite independent of the view cursor . The view cursor is visible on the screen and is manipulated by the user (and can be manipulated by program control), where as a text cursor is not visible on the screen and is solely used by program control. The following code snippet demonstrates creating a new text cursor, such that it starts at the same location as the viewCursor and is then moved independent of the view cursor. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oVC = thisComponent.getCurrentController.getViewCursor&lt;br /&gt;
oCursor = oVC.getText.createTextCursorByRange(oVC)&lt;br /&gt;
oCursor.gotoStartOfSentence(false)&lt;br /&gt;
oCursor.gotoEndOfSentence(true)&lt;br /&gt;
msgbox oCursor.getString&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Some objects are context dependent and get created using the method &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt; which is defined in the interface com.sun.star.lang.XMultiServiceFactory. For example to add a rectangle to the first page of a drawing document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
dim aPoint as new com.sun.star.awt.Point&lt;br /&gt;
dim aSize as new com.sun.star.awt.Size&lt;br /&gt;
 &lt;br /&gt;
aPoint.x = 1000&lt;br /&gt;
aPoint.y = 1000&lt;br /&gt;
 &lt;br /&gt;
aSize.Width = 10000&lt;br /&gt;
aSize.Height = 10000&lt;br /&gt;
 &lt;br /&gt;
oRectangleShape = thisComponent.createInstance(&amp;quot;com.sun.star.drawing.RectangleShape&amp;quot;)&lt;br /&gt;
oRectangleShape.Size = aSize&lt;br /&gt;
oRectangleShape.Position = aPoint&lt;br /&gt;
 &lt;br /&gt;
thisComponent.getDrawPages.getByIndex(0).add(oRectangleShape)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example also uses UNO structs see below for more information on UNO stucts. &lt;br /&gt;
&lt;br /&gt;
Some objects are context independent to create these objects use the OpenOffice.org Basic command createUnoService. For example to create the equivalent to StarDesktop: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDesktop = createUnoService(&amp;quot;com.sun.star.frame.Desktop&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The process that I use to determine how to access or create an object is as follows: &lt;br /&gt;
&lt;br /&gt;
Does the object already exist if so I should be able to access it from something like &amp;lt;tt&amp;gt;thisComponent&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Will the new object belong to another object, if so does the owner have a specific method for creating the object, if so use it. &lt;br /&gt;
&lt;br /&gt;
The new object will belong to another object, but that object doesn&amp;#039;t provide a specific method for creating it, but does provide &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt;. If the object doesn&amp;#039;t provide &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt; are you sure you are using the correct object, or is it context independent. &lt;br /&gt;
&lt;br /&gt;
I have found working out how to create an object to be quite difficult with existing documentation so I hope that this document/wiki will eventually make this clear. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==UNO structs==&lt;br /&gt;
UNO structures can be declared using the OpenOffice.org Basic command &amp;lt;tt&amp;gt;dim&amp;lt;/tt&amp;gt;: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
dim aPoint as new com.sun.star.awt.Point&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Or by using the OpenOffice.org Basic command &amp;lt;tt&amp;gt;createUnoStruct&amp;lt;/tt&amp;gt;: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
aPoint = createUnoStruct(&amp;quot;com.sun.star.awt.Point&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|When declaring UNO structs case is important. Note that everything upto the name of the struct is lowercase, and that the name of the struct is in TitleCase.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Creating Listeners and Handlers==&lt;br /&gt;
Through the user interface it is possible to assign macros to some events: &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org versions 1.1.x: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Configure… &amp;gt; Events&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org versions 1.9.x and above: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Customize… &amp;gt; Events&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
It is also possible to assign macros to a wider range of events using the OpenOffice.org Basic command CreateUnoListener. This same command is used for creating both listeners and handlers. A listener checks for an event and always allows other listeners to respond to the event as well. A handler listens for an event, and can optionally consume the event so that other listeners don&amp;#039;t get to act on it. &lt;br /&gt;
&lt;br /&gt;
The following example creates a keyHandler: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
global IannzExampleKeyHandler&lt;br /&gt;
 &lt;br /&gt;
sub SetupKeyHandler&lt;br /&gt;
oController = thisComponent.currentController&lt;br /&gt;
IannzExampleKeyHandler = CreateUnoListener(&amp;quot;KeyHandler_&amp;quot;,&amp;quot;com.sun.star.awt.XKeyHandler&amp;quot;)&lt;br /&gt;
oController.addKeyHandler(IannzExampleKeyHandler) &amp;#039; Register the listener&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
sub RemoveKeyHandler&lt;br /&gt;
thisComponent.currentController.removeKeyHandler(IannzExampleKeyHandler)&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
sub KeyHandler_disposing&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function KeyHandler_keyReleased(oKeyEvent as new com.sun.star.awt.KeyHandler) as boolean&lt;br /&gt;
        KeyHandler_keyReleased = False    &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function KeyHandler_keyPressed(oKeyEvent as new com.sun.star.awt.KeyHandler) as boolean&lt;br /&gt;
KeyHandler_keyPressed = false   &amp;#039;Let other listeners handle the event&lt;br /&gt;
if oKeyEvent.modifiers = com.sun.star.awt.KeyModifier.MOD2 then &amp;#039;Control key was pressed&lt;br /&gt;
        if oKeyEvent.keyCode = com.sun.star.awt.Key.Q then&lt;br /&gt;
                msgbox &amp;quot;Alt + Q was pressed&amp;quot;&lt;br /&gt;
                KeyHandler_keyPressed = true    &amp;#039;Don&amp;#039;t let other listeners process this event&lt;br /&gt;
        end if&lt;br /&gt;
end if&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
A variable declared as global keeps its value even after the macro exits. In this case we want to be able to use this variable later to remove the handler. As variables declared globally could be used in other libraries to try and avoid conflict I start all my global variables with Iannz my registered name for the OpenOffice.org web site. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;sub SetupKeyHandler&amp;lt;/tt&amp;gt; sets up the handler. The first parameter to CreateUnoListener is the staring name for the methods that will be called when that type of event occurs in this example .&amp;lt;tt&amp;gt;&amp;quot;KeyHandler_&amp;quot;&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
The second parameter is the name of the interface for the listener or handler, &amp;quot;com.sun.star.awt.XKeyHandler&amp;quot;. The name is case sensitive, everything up to and including the module name is always lowercase, the name of the interface always starts with &amp;quot;X&amp;quot; and the remainder is in TitleCase. &lt;br /&gt;
&lt;br /&gt;
Use the SDK to find out what methods the interface must supply. You must supply routines for all of these methods even if you don&amp;#039;t intend to use them. You also need to supply a disposing method. The names of these routines start with the string given in the first parameter to CreateUnoListener , in this example &amp;lt;tt&amp;gt;&amp;quot;KeyHandler_&amp;quot;&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Thus in the example there is &amp;lt;tt&amp;gt;KeyHandler_disposing&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;KeyHandler_keyReleased&amp;lt;/tt&amp;gt; which don&amp;#039;t actually do anything but are required, and &amp;lt;tt&amp;gt;KeyHandler_keyPressed&amp;lt;/tt&amp;gt; which actually does the job. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;sub RemoveKeyHandler&amp;lt;/tt&amp;gt; demonstrates how to remove the handler.&lt;br /&gt;
&lt;br /&gt;
=OpenOffice.org constants=&lt;br /&gt;
The above example uses OpenOffice.org constants. &lt;br /&gt;
&lt;br /&gt;
E.g. com.sun.star.awt.KeyModifier.MOD2&lt;br /&gt;
&lt;br /&gt;
OpenOffice.org constants are case sensitive. Everything up to and including the module name is always lowercase. The constant group is in TitleCase. The actual constant name is always UPPERCASE. &lt;br /&gt;
&lt;br /&gt;
Programmers not using OpenOffice.org Basic may not have access to these constants. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Using the recorder=&lt;br /&gt;
See [[ The OpenOffice.org recorder and UNO dispatch calls]] section for a discussion on recording UNO Dispatch commands versus writing API calls.&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Extensions_development_basic&amp;diff=7459</id>
		<title>Extensions development basic</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Extensions_development_basic&amp;diff=7459"/>
		<updated>2006-04-04T05:41:31Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;Getting started tutorial&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Before we can access the OpenOffice.org Basic Integrated Development Environment (IDE), to write some code, a decision needs to be made about where the code is to be stored. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Where do I write the code?=&lt;br /&gt;
OpenOffice.org Basic code is stored in modules within libraries. A library can be: &lt;br /&gt;
&lt;br /&gt;
*Shared (for a network install - OOo Macros &amp;amp; Dialogs) &lt;br /&gt;
*Just for the current user (My Macros &amp;amp; Dialogs) &lt;br /&gt;
*Within a document or template, so that its code is only available when that document is open.Within a document or template, so that its code is only available when that document is open. &lt;br /&gt;
Libraries not stored in a document or template (that is libraries that are shared or for the current user) are referred to as &amp;#039;&amp;#039;&amp;#039;OpenOffice.org libraries&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
To determine the actual folders that contain the OpenOffice.org libraries see:&amp;lt;br&amp;gt; &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Options… &amp;gt; OpenOffice.org &amp;gt; Paths &amp;gt; BASIC&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|Do not copy or move libraries using operating system commands. Use the macro organizer or package manager instead.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Modules within libraries have a maximum size of 64kb. A library can contain up to 16,000 modules. &lt;br /&gt;
&lt;br /&gt;
For more information see online help for: Modules and Libraries. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Accessing the IDE=&lt;br /&gt;
To access the IDE for the first time: &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org 1.1.x: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Macro… &amp;gt;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org 1.9.x and above: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Organize macros &amp;gt; OpenOffice.org Basic… &amp;gt;&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
To get started we will use Module1 in the Standard library which is stored for the current user only: &lt;br /&gt;
&lt;br /&gt;
Type a name for the new macro: &amp;#039;&amp;#039;&amp;#039;HelloWorld&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
In the macro from listbox select &amp;#039;&amp;#039;&amp;#039;Standard&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Click &amp;#039;&amp;#039;&amp;#039;New&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
You should now see something like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
REM  *****  BASIC  *****&lt;br /&gt;
 &lt;br /&gt;
Sub Main&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
 &lt;br /&gt;
Sub HelloWorld&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
The cursor will be positioned at the start of the &amp;lt;tt&amp;gt;Sub HelloWorld&amp;lt;/tt&amp;gt; line. &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|Now that while the IDE is running it can be accessed from the OpenOffice.org Window menu, or the task panel provided by the operating system.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Entering the code=&lt;br /&gt;
Select and delete: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
REM  *****  BASIC  *****&lt;br /&gt;
 &lt;br /&gt;
Sub Main&lt;br /&gt;
 &lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Below the line &amp;quot;Sub HelloWorld&amp;quot; type [[ msgbox]]&amp;lt;tt&amp;gt; &amp;quot;Hello World!&amp;quot;&amp;lt;/tt&amp;gt;, so that the editor looks like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Sub HelloWorld&lt;br /&gt;
msgbox &amp;quot;Hello World!&amp;quot;&lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Notes:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|The IDE does not provide code completion or help with command syntax as you type, but to get help on a Basic command position the cursor in the command and press F1.&amp;lt;br&amp;gt; OpenOffice.org Basic commands are not case sensitive. Thus msgbox, MSGBOX and Msgbox will all work.&amp;lt;br&amp;gt; Strings are enclosed in double quotes.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Running the code=&lt;br /&gt;
There are several ways of running the Basic code, these include: &lt;br /&gt;
&lt;br /&gt;
Directly from the IDE. There is a run button on the macro bar (by default the third control on the second toolbar). This will run the first macro in the current module. &lt;br /&gt;
&lt;br /&gt;
From the tools menu: (Version 1.1.x) &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macros &amp;gt; Macro…&amp;#039;&amp;#039;&amp;#039;; (Version 1.9.x and above) &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Macro &amp;gt; Run Macro…&amp;#039;&amp;#039;&amp;#039; &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a [[ key press]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a [[ menu entry]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to a toolbar button. &lt;br /&gt;
&lt;br /&gt;
Creating a [[ control in a document]]. &lt;br /&gt;
&lt;br /&gt;
Assigning the macro to an event. &lt;br /&gt;
&lt;br /&gt;
For now try running the &amp;quot;HelloWorld&amp;quot; subroutine by clicking the &amp;#039;&amp;#039;&amp;#039;Run&amp;#039;&amp;#039;&amp;#039; button. A small dialog titled &amp;quot;soffice&amp;quot; with the text &amp;quot;Hello World!&amp;quot; and an OK button should be displayed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Saving the code=&lt;br /&gt;
The code gets automatically saved whenever the container for the code gets saved. Thus, if the code is in an OpenOffice.org library (shared or users) then it gets automatically saved when OpenOffice.org exits. If the code is in a library which is part of a document it gets saved whenever the document is saved. &lt;br /&gt;
&lt;br /&gt;
On the Standard toolbar (by default the top toolbar) in the IDE there is a save button. If the code is in a document or template then clicking this button saves the entire document or template. If the code is in an OpenOffice.org library then just the current library gets saved. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Variables=&lt;br /&gt;
It is possible to force variable declaration with &amp;lt;tt&amp;gt;Option Explicit&amp;lt;/tt&amp;gt; at the top of the module. For a discussion on whether to declare variables or not see: [[http://www.oooforum.org/forum/viewtopic.phtml?t=5845 this discussion]]. &lt;br /&gt;
&lt;br /&gt;
In that discussion the initial author of this wiki thought that variables should always be declared. Since then he has changed to not declaring them. In short it is generally a personal preference. In either case, it is the initial authors preference that variables be named according to the following convention, which is used in the examples in this Wiki: &lt;br /&gt;
&lt;br /&gt;
The first letter of the variable name indicates the type of value that the variable is going to hold, as per the following table (based on a table in Tutorial.pdf by Sun) &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Letter&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;Meaning&amp;#039;&amp;#039;&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|-&lt;br /&gt;
|a&lt;br /&gt;
|Structure&lt;br /&gt;
|-&lt;br /&gt;
|b&lt;br /&gt;
|Boolean (TRUE or FALSE)&lt;br /&gt;
|-&lt;br /&gt;
|e&lt;br /&gt;
|Enumeration. This variable can only have one of a limited set of values.&lt;br /&gt;
|-&lt;br /&gt;
|f&lt;br /&gt;
|Float (3.402823 x 1038 to 1.401298 x 10-45. A single variable can take up to four bytes)&amp;lt;br&amp;gt; Double (1.79769313486232 x 10308 to 4.94065645841247 x 10-324. A double variable can take up to eight bytes)&amp;lt;br&amp;gt; Currency (-922337203685477.5808 to +922337203685477.5807 and takes up to eight bytes of memory)&lt;br /&gt;
|-&lt;br /&gt;
|m&lt;br /&gt;
|Array (aka sequence aka matrix)&lt;br /&gt;
|-&lt;br /&gt;
|n&lt;br /&gt;
|Integer (-32768 to 32767.) or&amp;lt;br&amp;gt; Long (-2147483648 and 2147483647).&lt;br /&gt;
|-&lt;br /&gt;
|o&lt;br /&gt;
|Object, service, or interface&lt;br /&gt;
|-&lt;br /&gt;
|s&lt;br /&gt;
|String (A string variable can store up to 65535 Unicode characters).&lt;br /&gt;
|-&lt;br /&gt;
|x&lt;br /&gt;
|Interface, to indicate that only operations of a particular interface of an object are used&lt;br /&gt;
|-&lt;br /&gt;
|v&lt;br /&gt;
|Variant, Any&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Use long descriptive variable names making use of camel case &lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|User defined OpenOffice.org Basic variables are not case sensitive. But UNO-API constants are case sensitive.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Convention exceptions to long descriptive names is for index variables where i, j, and k are commonly used, and for when a string is being built-up, where s is commonly used. &lt;br /&gt;
&lt;br /&gt;
Edit sub HelloWorld so that it looks like the following and run it: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub HelloWorld&lt;br /&gt;
dim i as integer &amp;#039;This line is optional&lt;br /&gt;
for i = 0 to 2&lt;br /&gt;
        &amp;#039;These lines are indented for ease of reading only&lt;br /&gt;
        msgbox &amp;quot;Hello World &amp;quot; &amp;amp; i&lt;br /&gt;
next&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
For more information on variables see: [[ using variables]]. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Understanding the OpenOffice.org API=&lt;br /&gt;
This section will start with an example. The remainder of this section aims to give information so that the example can be understood and expanded upon. &lt;br /&gt;
&lt;br /&gt;
Try running the following code with different types of documents being active. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
&amp;#039;basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
&amp;#039;xray.xray thisComponent&lt;br /&gt;
msgbox fnWhichComponent(thisComponent)&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function fnWhichComponent(oDoc) as string&lt;br /&gt;
if HasUnoInterfaces(oDoc, &amp;quot;com.sun.star.lang.XServiceInfo&amp;quot;) then &lt;br /&gt;
   if thisComponent.supportsService (&amp;quot;com.sun.star.text.GenericTextDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Text&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.sheet.SpreadsheetDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Spreadsheet&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.presentation.PresentationDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Presentation&amp;quot;&lt;br /&gt;
   elseif thisComponent.supportsService(&amp;quot;com.sun.star.drawing.GenericDrawingDocument&amp;quot;) then&lt;br /&gt;
      fnWhichComponent = &amp;quot;Drawing&amp;quot;&lt;br /&gt;
   else&lt;br /&gt;
      fnWhichComponent = &amp;quot;Oops current document something else&amp;quot;&lt;br /&gt;
   end if&lt;br /&gt;
else&lt;br /&gt;
   fnWhichComponent = &amp;quot;Not a document&amp;quot;&lt;br /&gt;
end if&lt;br /&gt;
End function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Subroutine naming convention==&lt;br /&gt;
In the above example the user defined function has a name that starts with the letters &amp;quot;fn&amp;quot;. This is the initial authors convention so that people know that this is a user defined function. Similarly, the initial author uses the convention that user defined subroutines start with the letters &amp;quot;sub&amp;quot;. When learning a language and an API it can be difficult to know what is built-in and what has been defined elsewhere. This document/wiki will use this convention for naming functions and subroutines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Introducing the OpenOffice.org API==&lt;br /&gt;
This section introduces the following terms: &lt;br /&gt;
&lt;br /&gt;
* Interface &lt;br /&gt;
* Module &lt;br /&gt;
* Service &lt;br /&gt;
* Method &lt;br /&gt;
* Property &lt;br /&gt;
&lt;br /&gt;
Understanding the difference between an interface and a service and what a module is, is not essential to being able to write extensions for OpenOffice.org, but it does help interpreting the documentation, and for introspection purposes. You may need to read this section at least twice. &lt;br /&gt;
&lt;br /&gt;
An &amp;#039;&amp;#039;&amp;#039;interface&amp;#039;&amp;#039;&amp;#039; is a &amp;#039;&amp;#039;definition&amp;#039;&amp;#039; of a set of methods (and their arguments) that a service which implements that interface must have. &lt;br /&gt;
&lt;br /&gt;
Interfaces are grouped together in &amp;#039;&amp;#039;&amp;#039;modules&amp;#039;&amp;#039;&amp;#039; for naming purposes. All interfaces (and services) start with the name &amp;quot;com.sun.star&amp;quot; then the name of the module then the name of the interface (or service). &lt;br /&gt;
&lt;br /&gt;
For example most services provide the com.sun.star.beans.XPropertySet interface. This interface is stored in the module &amp;quot;beans&amp;quot; and provides access to the properties of a service. A &amp;#039;&amp;#039;&amp;#039;property&amp;#039;&amp;#039;&amp;#039; is a value where as a &amp;#039;&amp;#039;&amp;#039;method&amp;#039;&amp;#039;&amp;#039; is an action. &lt;br /&gt;
&lt;br /&gt;
An OpenOffice.org object can have many services. &lt;br /&gt;
&lt;br /&gt;
An OpenOffice.org object may have a service, which implements an interface, in which a method description says that another OpenOffice.org object is returned.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Introspection==&lt;br /&gt;
HasUnoInterfaces is an OpenOffice.org Basic function for introspection. See this [[http://www.oooforum.org/forum/viewtopic.phtml?t=7068 link]] for information on introspection in other languages. &lt;br /&gt;
&lt;br /&gt;
HasUnoInterfaces returns true if all of the specified interfaces are available for the specified object. &lt;br /&gt;
&lt;br /&gt;
Most OpenOffice.org objects provide the method supportsService because they have the interface com.sun.star.lang.XServiceInfo. &lt;br /&gt;
&lt;br /&gt;
In the above example, the OpenOffice.org Basic command, &amp;#039;&amp;#039;&amp;#039;HasUnoInterfaces&amp;#039;&amp;#039;&amp;#039; checks that the current document has the interface com.sun.star.lang.XServiceInfo, because if it doesn&amp;#039;t have that interface then it doesn&amp;#039;t have the method supportsService, and a run time error would occur if such an object tried to access its nonexistent method. &lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;SupportsService&amp;#039;&amp;#039;&amp;#039; is a method which returns true if the specified service is available. The above examples checks for a service to determine the type of document that is currently active.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==X-Ray tool==&lt;br /&gt;
Using HasUnoInterfaces and supportsService gives information about an object at run time, but checking an object like this would be a nightmare for learning? Thankfully Bernard Marcelly has come to our rescue with the X-Ray tool. The X-Ray tool is available from: [[http://ooomacros.org/dev.php#101416 ooomacros]]. Download the zip file, unzip the document, open the document in OpenOffice.org, follow the instructions for installation and set-up. &lt;br /&gt;
&lt;br /&gt;
Part of the X-Ray tool set-up is to specify a local copy of the OpenOffice.org SDK. Download the OpenOffice.org SDK from and extract it. &lt;br /&gt;
&lt;br /&gt;
In the above example, at the start of the code, there are two commented lines (comments start with an apostrophe): &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039;basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
&amp;#039;xray.xray thisComponent&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Now that you have the X-Ray tool installed, uncomment these lines (remove the apostrophes) and rerun the macro. From version 5 of Xray the command simply becomes xray.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;BasicLibraries&amp;#039;&amp;#039;&amp;#039; is an OpenOffice.org Basic command that returns an object for accessing the OpenOffice.org libraries. The &amp;lt;tt&amp;gt;loadLibrary&amp;lt;/tt&amp;gt; method ensures that the routines in that library are available for use. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;xray.xray&amp;lt;/tt&amp;gt; specifies the xray library and the xray subroutine within that library, thisComponent is the object that is being passed to xray for introspection. &lt;br /&gt;
&lt;br /&gt;
To find the object that you want to work with often requires finding or creating it starting from either StarDesktop or thisComponent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Desktop, documents, and current selection==&lt;br /&gt;
StarDesktop and ThisComponent are OpenOffice.org Basic commands that refer to the application and currently active document respectively. &lt;br /&gt;
&lt;br /&gt;
Unlike Microsoft Office, OpenOffice.org is one application with different components. When running some code it maybe useful to check which component is currently active. The above code demonstrates how that checking process can be done. &lt;br /&gt;
&lt;br /&gt;
The Desktop that StarDesktop refers to is conceptual (historically it actually existed) and can be thought of as the OpenOffice.org application.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Creating new documents==&lt;br /&gt;
To create a new text document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/swriter&amp;quot;, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To create a new spreadsheet document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/scalc&amp;quot;, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
An easier approach would be to write a simple function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnNewDoc(sDocType as string)&lt;br /&gt;
fnNewDoc = StarDesktop.loadComponentFromURL(&amp;quot;private:factory/&amp;quot; &amp;amp; sDocType , &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Then creating new documents can be achieved with: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;swriter&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;scalc&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;simpress&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;sdraw&amp;quot;)&lt;br /&gt;
oDoc = fnNewDoc(&amp;quot;smath&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
See [[ loadComponentFromUrl]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==To open a document==&lt;br /&gt;
The following example shows how to open a file. For information on URLs in OpenOffice.org see [[ URL Basics]]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sFile = &amp;quot;C:\Documents and Settings\danny\Desktop\MyCalc.sxc&amp;quot; &amp;#039; Windows&lt;br /&gt;
sFile = &amp;quot;/home/danny/Desktop/MyCalc.sxc&amp;quot; &amp;#039; Linux&lt;br /&gt;
sURL = ConvertToURL(sFile)&lt;br /&gt;
oDoc = StarDesktop.loadComponentFromURL(sURL, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Again it may make sense to make this easier by writing a simple function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
function fnOpenDoc(sFile)&lt;br /&gt;
sURL = ConvertToURL(sFile)&lt;br /&gt;
fnOpenDoc = StarDesktop.loadComponentFromURL(sURL, &amp;quot;_blank&amp;quot;, 0, Array())&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Examples of calling the function: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDoc = fnOpenDoc(&amp;quot;C:\Documents and Settings\danny\Desktop\MyCalc.sxc&amp;quot;) &amp;#039; Windows&lt;br /&gt;
oDoc = fnOpenDoc(&amp;quot;/home/danny/Desktop/MyCalc.sxc&amp;quot;) &amp;#039; Linux&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Current Selection==&lt;br /&gt;
It is common to want to run some code that effects the current selection. &amp;lt;tt&amp;gt;ThisComponent&amp;lt;/tt&amp;gt; has the method &amp;lt;tt&amp;gt;getCurrentSelection&amp;lt;/tt&amp;gt;. Since many different types of objects could possibly be selected it is common to check that the currently selected object has the service that contains the method that we want to apply to the object. &lt;br /&gt;
&lt;br /&gt;
Edit the main subroutine to the following and rerun it on a text document with different selections. (To select more than one block of text hold down the control key). &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
if fnWhichComponent(thisComponent) = &amp;quot;Text&amp;quot; then&lt;br /&gt;
        oCurSelection = thisComponent.getCurrentSelection()&lt;br /&gt;
        &amp;#039;xray.xray oCurSelection&lt;br /&gt;
        if oCurSelection.supportsService(&amp;quot;com.sun.star.text.TextRanges&amp;quot;) then&lt;br /&gt;
                msgbox &amp;quot;There are &amp;quot; &amp;amp; oCurSelection.getCount() &amp;amp; _&lt;br /&gt;
                 &amp;quot; selections in the current text document.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
With nothing selected the number of selections is one - the insertion point, with one block of text selected the count is still one, but with two blocks of text the count is three - the insertion point and the two blocks of selected text. &lt;br /&gt;
&lt;br /&gt;
Exercise 1: Modify the above code so that it works on selected cell ranges in a spreadsheet. &lt;br /&gt;
&lt;br /&gt;
Question1: For two blocks of cells selected, what would be the count for the number of selections? &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Properties==&lt;br /&gt;
Uncomment &amp;lt;tt&amp;gt;&amp;#039;xray.xray oCurSelection&amp;lt;/tt&amp;gt; so that xray runs, to see that the object that &amp;lt;tt&amp;gt;oCurSelection&amp;lt;/tt&amp;gt; points to has a &amp;quot;property&amp;quot; called &amp;lt;tt&amp;gt;Count&amp;lt;/tt&amp;gt; with a description of &amp;quot;pseudo-prop, read only&amp;quot;. It is possible in OpenOffice.org Basic to write &amp;lt;tt&amp;gt;oCurSelection.count&amp;lt;/tt&amp;gt;, but as this is not possible in all other languages accessing the OpenOffice.org API, this Wiki will try to always use the method approach. (I say try because I have not been in the habit of doing this and sometimes I may forget). &lt;br /&gt;
&lt;br /&gt;
This next example demonstrates changing a property value for the current selections. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
sub main&lt;br /&gt;
basicLibraries.loadLibrary(&amp;quot;Xray&amp;quot;)&lt;br /&gt;
if fnWhichComponent(thisComponent) = &amp;quot;Text&amp;quot; then&lt;br /&gt;
   oCurSelection = thisComponent.getCurrentSelection()&lt;br /&gt;
   if oCurSelection.supportsService(&amp;quot;com.sun.star.text.TextRanges&amp;quot;) then&lt;br /&gt;
      nCount = oCurSelection.Count&lt;br /&gt;
      &amp;#039;xray.xray oCurSelection.getByIndex(0)&lt;br /&gt;
      &amp;#039;Warning: The insertion point will have the same action applied twice&lt;br /&gt;
      &amp;#039;in this case it doesn&amp;#039;t matter, but in others it might.&lt;br /&gt;
      for i = 0 to nCount - 1&lt;br /&gt;
         oCurSelection.getByIndex(i).setPropertyValue(&amp;quot;CharStyleName&amp;quot;, &amp;quot;Strong Emphasis&amp;quot;)&lt;br /&gt;
      next&lt;br /&gt;
   end if&lt;br /&gt;
end if&lt;br /&gt;
end sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
In OpenOffice.org Basic it is possible to shorten the assignment line to: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oCurSelection(i).CharStyleName = &amp;quot;Strong Emphasis&amp;quot;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This wiki will try to use the full methods for both indexing and assigning properties. The rationale is that this makes converting the code to other languages easier and also helps the learner to understand what is happening (again I have not been in the habit of doing this so some examples may slip past me). &lt;br /&gt;
&lt;br /&gt;
Exercise 2: Rewrite the above code so that the warning can be removed. &lt;br /&gt;
&lt;br /&gt;
See [[ Current selection]]. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Iterative Access to Subordinate Objects (Enumeration access)=&lt;br /&gt;
Sometimes to access the desired object an enumeration is required. For example paragraphs, within a document or within a selection. &lt;br /&gt;
&lt;br /&gt;
When a Writer document is active and some text is selected, both &amp;lt;tt&amp;gt;thisDocument.getText()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;thisComponent.getCurrentSelection().getByIndex(i)&amp;lt;/tt&amp;gt; have the service: com.sun.star.text.TextRange which has the interface: com.sun.star.container.XContentEnumerationAccess, it is possible to create an enumeration of the paragraphs for the current document or for a particular selection. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
&amp;#039; Create enumeration object&lt;br /&gt;
oTextElementEnum = thisComponent.getText().createEnumeration()&lt;br /&gt;
&amp;#039;or thisComponent.getCurrentSelection().getByIndex(i).createEnumeration()&lt;br /&gt;
 &lt;br /&gt;
&amp;#039; loop over all text elements&lt;br /&gt;
while oTextElementEnum.hasMoreElements()&lt;br /&gt;
        oTextElement = oTextElementEnum.nextElement&lt;br /&gt;
        if oTextElement.supportsService(&amp;quot;com.sun.star.text.TextTable&amp;quot;) then&lt;br /&gt;
                MsgBox &amp;quot;The current block contains a table.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
        if oTextElement.supportsService(&amp;quot;com.sun.star.text.Paragraph&amp;quot;) then&lt;br /&gt;
                MsgBox &amp;quot;The current block contains a paragraph.&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
wend&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Exercise 3: Extend the above example to display in a message box all text portions that are bold. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Named access=&lt;br /&gt;
Some objects provide named access to a particular type of subordinate object, some others indexed access, and some both named and indexed access. &lt;br /&gt;
&lt;br /&gt;
For example if the current document in OpenOffice.org is a spreadsheet then to access a particular sheet can be done by index access: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oSheet = thisComponent.getSheets.getByIndex(0)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
or named access: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oSheet = thisComponent.getSheets.getByName(&amp;quot;Sheet1&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To check if an object with a particular name already exists use &amp;lt;tt&amp;gt;hasByName&amp;lt;/tt&amp;gt;, for example: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
if thisComponent.getSheets.hasByName(&amp;quot;Sheet1&amp;quot;) then&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
To loop through all the available object names can be done like: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
mNames = thisComponent.getSheets.getElementnames&lt;br /&gt;
for i = lbound(mNames) to ubound(mNames)&lt;br /&gt;
        msgbox mNames(i)&lt;br /&gt;
next&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Some named subordinate objects also provide the interface:  com.sun.star.container.XNameContainer. This interface defines that such objects should have the following methods: &amp;lt;tt&amp;gt;insertByName&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;replaceByname&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;removeByName&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
E.g. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
thisComponent.getSheets.insertByName(&amp;quot;NewSheet&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Create new objects=&lt;br /&gt;
Some objects have services which implement interfaces to provide specific methods for creating a particular type of object. &lt;br /&gt;
&lt;br /&gt;
For example if the current document is a Writer document then &amp;lt;tt&amp;gt;thisComponent.getText&amp;lt;/tt&amp;gt; is an object that provides the service com.sun.star.text.Text which implements the interface  com.sun.star.text.XSimpleText which defines the methods &amp;lt;tt&amp;gt;createTextCursor&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;createTextCursorByRange&amp;lt;/tt&amp;gt;. Both of these methods create a text cursor for accessing the text of the document. These cursors are quite independent of the view cursor . The view cursor is visible on the screen and is manipulated by the user (and can be manipulated by program control), where as a text cursor is not visible on the screen and is solely used by program control. The following code snippet demonstrates creating a new text cursor, such that it starts at the same location as the viewCursor and is then moved independent of the view cursor. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oVC = thisComponent.getCurrentController.getViewCursor&lt;br /&gt;
oCursor = oVC.getText.createTextCursorByRange(oVC)&lt;br /&gt;
oCursor.gotoStartOfSentence(false)&lt;br /&gt;
oCursor.gotoEndOfSentence(true)&lt;br /&gt;
msgbox oCursor.getString&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Some objects are context dependent and get created using the method &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt; which is defined in the interface com.sun.star.lang.XMultiServiceFactory. For example to add a rectangle to the first page of a drawing document: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
dim aPoint as new com.sun.star.awt.Point&lt;br /&gt;
dim aSize as new com.sun.star.awt.Size&lt;br /&gt;
 &lt;br /&gt;
aPoint.x = 1000&lt;br /&gt;
aPoint.y = 1000&lt;br /&gt;
 &lt;br /&gt;
aSize.Width = 10000&lt;br /&gt;
aSize.Height = 10000&lt;br /&gt;
 &lt;br /&gt;
oRectangleShape = thisComponent.createInstance(&amp;quot;com.sun.star.drawing.RectangleShape&amp;quot;)&lt;br /&gt;
oRectangleShape.Size = aSize&lt;br /&gt;
oRectangleShape.Position = aPoint&lt;br /&gt;
 &lt;br /&gt;
thisComponent.getDrawPages.getByIndex(0).add(oRectangleShape)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
This example also uses UNO structs see below for more information on UNO stucts. &lt;br /&gt;
&lt;br /&gt;
Some objects are context independent to create these objects use the OpenOffice.org Basic command [[ createUnoService]]. For example to create the equivalent to StarDesktop: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
oDesktop = createUnoService(&amp;quot;com.sun.star.frame.Desktop&amp;quot;)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The process that I use to determine how to access or create an object is as follows: &lt;br /&gt;
&lt;br /&gt;
Does the object already exist if so I should be able to access it from something like &amp;lt;tt&amp;gt;thisComponent&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Will the new object belong to another object, if so does the owner have a specific method for creating the object, if so use it. &lt;br /&gt;
&lt;br /&gt;
The new object will belong to another object, but that object doesn&amp;#039;t provide a specific method for creating it, but does provide &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt;. If the object doesn&amp;#039;t provide &amp;lt;tt&amp;gt;createInstance&amp;lt;/tt&amp;gt; are you sure you are using the correct object, or is it context independent. &lt;br /&gt;
&lt;br /&gt;
I have found working out how to create an object to be quite difficult with existing documentation so I hope that this document/wiki will eventually make this clear. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==UNO structs==&lt;br /&gt;
UNO structures can be declared using the OpenOffice.org Basic command &amp;lt;tt&amp;gt;dim&amp;lt;/tt&amp;gt;: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
dim aPoint as new com.sun.star.awt.Point&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Or by using the OpenOffice.org Basic command &amp;lt;tt&amp;gt;createUnoStruct&amp;lt;/tt&amp;gt;: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
aPoint = createUnoStruct(&amp;quot;com.sun.star.awt.Point&amp;quot;)&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|&amp;#039;&amp;#039;&amp;#039;Note:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
|When declaring UNO structs case is important. Note that everything upto the name of the struct is lowercase, and that the name of the struct is in TitleCase.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Creating Listeners and Handlers==&lt;br /&gt;
Through the user interface it is possible to assign macros to some events: &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org versions 1.1.x: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Configure… &amp;gt; Events&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
OpenOffice.org versions 1.9.x and above: &amp;#039;&amp;#039;&amp;#039;Tools &amp;gt; Customize… &amp;gt; Events&amp;#039;&amp;#039;&amp;#039;. &lt;br /&gt;
&lt;br /&gt;
It is also possible to assign macros to a wider range of events using the OpenOffice.org Basic command CreateUnoListener. This same command is used for creating both listeners and handlers. A listener checks for an event and always allows other listeners to respond to the event as well. A handler listens for an event, and can optionally consume the event so that other listeners don&amp;#039;t get to act on it. &lt;br /&gt;
&lt;br /&gt;
The following example creates a keyHandler: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
global IannzExampleKeyHandler&lt;br /&gt;
 &lt;br /&gt;
sub SetupKeyHandler&lt;br /&gt;
oController = thisComponent.currentController&lt;br /&gt;
IannzExampleKeyHandler = CreateUnoListener(&amp;quot;KeyHandler_&amp;quot;,&amp;quot;com.sun.star.awt.XKeyHandler&amp;quot;)&lt;br /&gt;
oController.addKeyHandler(IannzExampleKeyHandler) &amp;#039; Register the listener&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
sub RemoveKeyHandler&lt;br /&gt;
thisComponent.currentController.removeKeyHandler(IannzExampleKeyHandler)&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
sub KeyHandler_disposing&lt;br /&gt;
end sub&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function KeyHandler_keyReleased(oKeyEvent as new com.sun.star.awt.KeyHandler) as boolean&lt;br /&gt;
        KeyHandler_keyReleased = False    &lt;br /&gt;
end function&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
function KeyHandler_keyPressed(oKeyEvent as new com.sun.star.awt.KeyHandler) as boolean&lt;br /&gt;
KeyHandler_keyPressed = false   &amp;#039;Let other listeners handle the event&lt;br /&gt;
if oKeyEvent.modifiers = com.sun.star.awt.KeyModifier.MOD2 then &amp;#039;Control key was pressed&lt;br /&gt;
        if oKeyEvent.keyCode = com.sun.star.awt.Key.Q then&lt;br /&gt;
                msgbox &amp;quot;Alt + Q was pressed&amp;quot;&lt;br /&gt;
                KeyHandler_keyPressed = true    &amp;#039;Don&amp;#039;t let other listeners process this event&lt;br /&gt;
        end if&lt;br /&gt;
end if&lt;br /&gt;
end function&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
A variable declared as global keeps its value even after the macro exits. In this case we want to be able to use this variable later to remove the handler. As variables declared globally could be used in other libraries to try and avoid conflict I start all my global variables with Iannz my registered name for the OpenOffice.org web site. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;sub SetupKeyHandler&amp;lt;/tt&amp;gt; sets up the handler. The first parameter to CreateUnoListener is the staring name for the methods that will be called when that type of event occurs in this example .&amp;lt;tt&amp;gt;&amp;quot;KeyHandler_&amp;quot;&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
The second parameter is the name of the interface for the listener or handler, &amp;quot;com.sun.star.awt.XKeyHandler&amp;quot;. The name is case sensitive, everything up to and including the module name is always lowercase, the name of the interface always starts with &amp;quot;X&amp;quot; and the remainder is in TitleCase. &lt;br /&gt;
&lt;br /&gt;
Use the SDK to find out what methods the interface must supply. You must supply routines for all of these methods even if you don&amp;#039;t intend to use them. You also need to supply a disposing method. The names of these routines start with the string given in the first parameter to CreateUnoListener , in this example &amp;lt;tt&amp;gt;&amp;quot;KeyHandler_&amp;quot;&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Thus in the example there is &amp;lt;tt&amp;gt;KeyHandler_disposing&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;KeyHandler_keyReleased&amp;lt;/tt&amp;gt; which don&amp;#039;t actually do anything but are required, and &amp;lt;tt&amp;gt;KeyHandler_keyPressed&amp;lt;/tt&amp;gt; which actually does the job. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;sub RemoveKeyHandler&amp;lt;/tt&amp;gt; demonstrates how to remove the handler. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=OpenOffice.org constants=&lt;br /&gt;
The above example uses OpenOffice.org constants. &lt;br /&gt;
&lt;br /&gt;
E.g. com.sun.star.awt.KeyModifier.MOD2&lt;br /&gt;
&lt;br /&gt;
OpenOffice.org constants are case sensitive. Everything up to and including the module name is always lowercase. The constant group is in TitleCase. The actual constant name is always UPPERCASE. &lt;br /&gt;
&lt;br /&gt;
Programmers not using OpenOffice.org Basic may not have access to these constants. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Using the recorder=&lt;br /&gt;
See [[ The OpenOffice.org recorder and UNO dispatch calls]] section for a discussion on recording UNO Dispatch commands versus writing API calls.&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=Extensions_development&amp;diff=7455</id>
		<title>Extensions development</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=Extensions_development&amp;diff=7455"/>
		<updated>2006-04-04T04:29:08Z</updated>

		<summary type="html">&lt;p&gt;Iannz: /* Starting in a language */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Extensions}}&lt;br /&gt;
Developing extensions is an efficient way to bring value to OpenOffice.org without diving into core sources. Obviously all developers willing to [[Main_Page|develop at OpenOffice.org sources level]] are welcomed.&lt;br /&gt;
&lt;br /&gt;
OpenOffice.org enables third party tools creation through UNO bridges, allowing using many languages.&lt;br /&gt;
&lt;br /&gt;
The principle is to create UNO packages that can be listed in the OpenOffice.org [[Extensions_repository|Extensions repository]] and installed by end-users easily.&lt;br /&gt;
&lt;br /&gt;
This section wants to give newcomers as well as experienced developers some hints to develop Extensions in their desired languages and provide them with tools and frameworks that ease and homogenize the development.&lt;br /&gt;
&lt;br /&gt;
Finally, popular Extensions may be integrated into OpenOffice.org so it is important to follow common policies from beginning to ease this merging.&lt;br /&gt;
&lt;br /&gt;
==== Starting in a language ====&lt;br /&gt;
Addons can be written in various languages. Each section is here to give starting informations that let you create your addons. Each section is dedicated to a language. It deals with specific points concerning the Extensions aspect. Resources regarding the OpenOffice.org API can be found on the [http://api.openoffice.org API project] and UNO bridges languages issues on the [http://udk.openoffice.org UDK project]&lt;br /&gt;
&lt;br /&gt;
The translations of these pages are welcomed and [[Extensions#Translating_these_pages|guidelines are available]].&lt;br /&gt;
&lt;br /&gt;
* [[Extensions_development_python|Starting in Python]]&lt;br /&gt;
* [[Extensions_development_basic|Starting in Basic]]&lt;br /&gt;
* [[Extensions_development_java|Starting in Java]]&lt;br /&gt;
* Starting in C++&lt;br /&gt;
* Non programmatic Extensions&lt;br /&gt;
* Extensions packaging&lt;br /&gt;
&lt;br /&gt;
==== Tools &amp;amp; Frameworks ====&lt;br /&gt;
&lt;br /&gt;
* [[Extensions_development_translation|Translation framework]]&lt;br /&gt;
* Extension Packager&lt;br /&gt;
* Predefined wizards&lt;br /&gt;
* Introspection Tools : discover the API&lt;br /&gt;
&lt;br /&gt;
[[Category:Extensions]]&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=User:Iannz&amp;diff=2079</id>
		<title>User:Iannz</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=User:Iannz&amp;diff=2079"/>
		<updated>2005-11-17T21:10:14Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Test&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=MediaWiki_Configuration&amp;diff=2049</id>
		<title>MediaWiki Configuration</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=MediaWiki_Configuration&amp;diff=2049"/>
		<updated>2005-11-16T21:46:35Z</updated>

		<summary type="html">&lt;p&gt;Iannz: /* CodeSyntaxHighlight MediaWiki Extension */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This pages have been automatically generated by twiki2mediawiki. Please&lt;br /&gt;
review all of them, as there will be broken markup and broken links.&lt;br /&gt;
&lt;br /&gt;
Please review your page and move the link from the &amp;quot;Converted Pages&amp;quot; to &amp;quot;Reviewed Pages&amp;quot;. To move your page to a new name you have to login. If you would like to see a page removed add a link to the [[Twiki2mediawiki_TODO_list#remove.28d.29|remove(d)]] section.&lt;br /&gt;
&lt;br /&gt;
== Reviewed Pages ==&lt;br /&gt;
&lt;br /&gt;
=== ok ===&lt;br /&gt;
&lt;br /&gt;
* [[OOo Ergonomics]] (from [[Main_OOoAnnoyances]])&lt;br /&gt;
* [[OpenDocument]]&lt;br /&gt;
* [[OpenOffice]]&lt;br /&gt;
* [[Main_IRCCommunication]]&lt;br /&gt;
* [[Main_OOoJava]]&lt;br /&gt;
* [[OOoRelease201]]&lt;br /&gt;
* [[ProductRelease]]&lt;br /&gt;
* [[Main_OOoRelease200]]&lt;br /&gt;
* [[Writing_warning-free_code]] (from [[Main_WarningFree]])&lt;br /&gt;
&lt;br /&gt;
SVG* got re-worked by Haui&lt;br /&gt;
* [[Main_SVGGroupOpacity]]&lt;br /&gt;
* [[Main_SVGEllipticArcs]]&lt;br /&gt;
* [[Main_SVGImportFilter]]&lt;br /&gt;
* [[Main_SVGSupportedFeatures]]&lt;br /&gt;
* [[Main_SVGUnsupportedFeatures]]&lt;br /&gt;
* [[Main_SVGFilterSourceCode]]&lt;br /&gt;
* [[Main_SVGUserExperiences]]&lt;br /&gt;
* [[Main_SVGPathSemantics]]&lt;br /&gt;
* [[Main_SVGHEAD]]&lt;br /&gt;
* [[Main_SVGImportTodo]]&lt;br /&gt;
* [[Main_SVGCoordinateSystems]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== remove(d) ===&lt;br /&gt;
&lt;br /&gt;
Please add a link to pages you would like to see removed here.&lt;br /&gt;
&lt;br /&gt;
* [[_default_WebLeftBar]]&lt;br /&gt;
* [[_default_WebRss]]&lt;br /&gt;
* [[Main_CaioTiago]]&lt;br /&gt;
* [[Main_OOo]]&lt;br /&gt;
* [[Main_EikeRathke]]&lt;br /&gt;
* [[Main_IanNz]]&lt;br /&gt;
* [[Main_JacquelineMcNally]]&lt;br /&gt;
* [[Main_LondonOffice]]&lt;br /&gt;
* [[Main_OfficeLocations]]&lt;br /&gt;
* [[Main_SanJoseOffice]]&lt;br /&gt;
* [[Main_StefanTaxhet]]&lt;br /&gt;
* [[Main_TokyoOffice]]&lt;br /&gt;
* [[Main_MichaelMeeks]]&lt;br /&gt;
* [[Sandbox_MyPlayGround]]&lt;br /&gt;
* [[Sandbox_StefanTaxhetSandbox]]&lt;br /&gt;
* [[Sandbox_WebLeftBar]]&lt;br /&gt;
* [[Sandbox_WebRss]]&lt;br /&gt;
* [[Main_WebRss]]&lt;br /&gt;
* [[Main_TestTest]]&lt;br /&gt;
* [[Main_StefanTaxhetAdmin]]&lt;br /&gt;
* [[Sandbox_SurveyServicesOpenOfficeOrg]]&lt;br /&gt;
* [[Main_TOCStyleInclude]]&lt;br /&gt;
* [[Main_CodeStyleInclude]]&lt;br /&gt;
* [[Main_DianeMackay]]&lt;br /&gt;
* [[Main_StephanBergmann]]&lt;br /&gt;
&lt;br /&gt;
These pages are of dubious usefulness, completeness &amp;amp; relevance and should prolly be removed:&lt;br /&gt;
* [[WebOOoBanners]]&lt;br /&gt;
* [[OOoES]]&lt;br /&gt;
&lt;br /&gt;
== Converted Pages - pending re-work ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s good if you rename these pages as they are re-worked to remove the &amp;#039;Main_&amp;#039; suffix - use the &amp;#039;move&amp;#039; tab to do that.&lt;br /&gt;
&lt;br /&gt;
* [[DomainDeveloper]]&lt;br /&gt;
* [[Main_SurveyServicesOpenOfficeOrg]]&lt;br /&gt;
* [[Main_MacOSXBuildInstructions]]&lt;br /&gt;
* [[Main_ReleaseMilestone]]&lt;br /&gt;
* [[Main_ReleaseCodeline]]&lt;br /&gt;
* [[Main_TargetMilestone]]&lt;br /&gt;
&lt;br /&gt;
== Personal Pages ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s probable that we don&amp;#039;t want / require personal pages in the wiki. Hence this lot can be axed in a week or two if no-one screams, many of them contain broken Twiki junk.&lt;br /&gt;
To help us with this process, it&amp;#039;d be great if you could remove the content from your page &amp;amp; move your name into the relevant &amp;#039;remove(d)&amp;#039; section above to join the other alumnii there.&lt;br /&gt;
&lt;br /&gt;
* [[Main_AlanKatzman]]&lt;br /&gt;
* [[Main_AlexandroColorado]]&lt;br /&gt;
* [[Main_AlexBrooks]]&lt;br /&gt;
* [[Main_AndreSchnabel]]&lt;br /&gt;
* [[Main_AndrewBrown]]&lt;br /&gt;
* [[Main_BadBoy]]&lt;br /&gt;
* [[Main_BerndSeidler]]&lt;br /&gt;
* [[Main_BernhardHaumacher]]&lt;br /&gt;
* [[Main_CharlesSchulz]]&lt;br /&gt;
* [[Main_ChrisReid]]&lt;br /&gt;
* [[Main_ChristophNeumann]]&lt;br /&gt;
* [[Main_CorNouws]]&lt;br /&gt;
* [[Main_CraigAdams]]&lt;br /&gt;
* [[Main_CristianDriga]]&lt;br /&gt;
* [[Main_CyrilJacquenot]]&lt;br /&gt;
* [[Main_CyrilRIP]]&lt;br /&gt;
* [[Main_DavidFraser]]&lt;br /&gt;
* [[Main_DeepankarDatta]]&lt;br /&gt;
* [[Main_DonaldGillies]]&lt;br /&gt;
* [[Main_DrewCrosland]]&lt;br /&gt;
* [[Main_EricBachard]]&lt;br /&gt;
* [[Main_EricHoch]]&lt;br /&gt;
* [[Main_ErnestoWalker]]&lt;br /&gt;
* [[Main_FlorianHeckl]]&lt;br /&gt;
* [[Main_FrankSchoenheit]]&lt;br /&gt;
* [[Main_FriedrichStrohmaier]]&lt;br /&gt;
* [[Main_GorkemCetin]]&lt;br /&gt;
* [[Main_GrSingleton]]&lt;br /&gt;
* [[Main_HelenePetit]]&lt;br /&gt;
* [[Main_JacquesRoux]]&lt;br /&gt;
* [[Main_JimWatson]]&lt;br /&gt;
* [[Main_JiriReznicek]]&lt;br /&gt;
* [[Main_JohannesSwoboda]]&lt;br /&gt;
* [[Main_JoostAndrae]]&lt;br /&gt;
* [[Main_JuergenSchmidt]]&lt;br /&gt;
* [[Main_KazunariHirano]]&lt;br /&gt;
* [[Main_KoheiYoshida]]&lt;br /&gt;
* [[Main_LaptopPerKidLetter]]&lt;br /&gt;
* [[Main_LouisSuarez]]&lt;br /&gt;
* [[Main_LuisCabreraSauco]]&lt;br /&gt;
* [[Main_MaartenBrouwers]]&lt;br /&gt;
* [[Main_MarcMaki]]&lt;br /&gt;
* [[Main_MarkoMoeller]]&lt;br /&gt;
* [[Main_MarkusHibbetts]]&lt;br /&gt;
* [[Main_MartinTaylor]]&lt;br /&gt;
* [[Main_MikeStockman]]&lt;br /&gt;
* [[Main_OpenTiss]]&lt;br /&gt;
* [[Main_PaoloMantovani]]&lt;br /&gt;
* [[Main_PatrickBall]]&lt;br /&gt;
* [[Main_PaulWujek]]&lt;br /&gt;
* [[Main_PavelJanik]]&lt;br /&gt;
* [[Main_PeteBedingfield]]&lt;br /&gt;
* [[Main_PeterEberlein]]&lt;br /&gt;
* [[Main_PeterThoeny]]&lt;br /&gt;
* [[Main_RalfSchellenberger]]&lt;br /&gt;
* [[Main_ReneAuberger]]&lt;br /&gt;
* [[Main_RobertRees]]&lt;br /&gt;
* [[Main_RolfMeyer]]&lt;br /&gt;
* [[Main_ScottCarr]]&lt;br /&gt;
* [[Main_SeoCoolhuoquoz]]&lt;br /&gt;
* [[Main_SettanttaOo]]&lt;br /&gt;
* [[Main_StephanBergmann]]&lt;br /&gt;
* [[Main_SuperBiskit]]&lt;br /&gt;
* [[Main_SvanteSchubert]]&lt;br /&gt;
* [[Main_Syndication]]&lt;br /&gt;
* [[Main_TheTschaena]]&lt;br /&gt;
* [[Main_VincentPatrick]]&lt;br /&gt;
* [[Sandbox_AndrewBrownSandbox]]&lt;br /&gt;
* [[Sandbox_BernhardHaumacherSandbox]]&lt;br /&gt;
* [[Sandbox_CristianDrigaSandbox]]&lt;br /&gt;
* [[Sandbox_ScottCarrSandbox]]&lt;br /&gt;
&lt;br /&gt;
== Managing Rights ==&lt;br /&gt;
&lt;br /&gt;
* sysop via db&amp;lt;br&amp;gt;&lt;br /&gt;
http://meta.wikimedia.org/wiki/Setting_user_rights_in_MediaWiki#Granting_rights_to_users&lt;br /&gt;
&lt;br /&gt;
* [http://meta.wikimedia.org/wiki/User_rights User Rights]&lt;br /&gt;
&lt;br /&gt;
It seems neccessary to require users to login to edit.&amp;lt;br&amp;gt;&lt;br /&gt;
This avoids defacement and makes authors feel more responsible for&lt;br /&gt;
the content.&lt;br /&gt;
&lt;br /&gt;
Special Pages to take care of:&lt;br /&gt;
* Special:Userrights&lt;br /&gt;
* OOoWiki:Administrators&lt;br /&gt;
&lt;br /&gt;
== Help Content (done) ==&lt;br /&gt;
&lt;br /&gt;
Help:Contents with links to &amp;lt;br&amp;gt;&lt;br /&gt;
http://meta.wikimedia.org/wiki/MediaWiki_FAQ &amp;lt;br&amp;gt;&lt;br /&gt;
http://meta.wikimedia.org/wiki/MediaWiki_User%27s_Guide&lt;br /&gt;
&lt;br /&gt;
Help:Editing with links to &amp;lt;br&amp;gt;&lt;br /&gt;
http://meta.wikimedia.org/wiki/Help:Editing &amp;lt;br&amp;gt;&lt;br /&gt;
http://meta.wikimedia.org/wiki/Help:Contents#For_editors&lt;br /&gt;
&lt;br /&gt;
== Copyrights (done) ==&lt;br /&gt;
&lt;br /&gt;
[[Project:Copyrights]]&lt;br /&gt;
&lt;br /&gt;
== Navigation Box (done) ==&lt;br /&gt;
&lt;br /&gt;
See http://meta.wikimedia.org/wiki/MediaWiki_FAQ#In_version_1.5&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[MediaWiki:Sidebar]]&lt;br /&gt;
&lt;br /&gt;
== InterWiki Links ==&lt;br /&gt;
&lt;br /&gt;
http://meta.wikimedia.org/wiki/Help:Guide_for_system_administrators_for_setting_up_interwiki_linking#add_your_own_custom&lt;br /&gt;
&lt;br /&gt;
[[User:Haui]] configured issue InterWiki links for TWiki. That would be handy here too.&lt;br /&gt;
&lt;br /&gt;
== Custom Namespaces ==&lt;br /&gt;
&lt;br /&gt;
http://meta.wikimedia.org/wiki/Help:Custom_namespaces&lt;br /&gt;
&lt;br /&gt;
== Cleanup Test Installations ==&lt;br /&gt;
&lt;br /&gt;
mediawiki2, mediawiki, backups of httpd.conf, ... can be purged.&lt;br /&gt;
&lt;br /&gt;
We might want to keep one playground though.&lt;br /&gt;
&lt;br /&gt;
== CodeSyntaxHighlight MediaWiki Extension ==&lt;br /&gt;
Code Syntax highlighting using GeShi&lt;br /&gt;
http://qbnz.com/highlighter/&lt;br /&gt;
Has been added as per&lt;br /&gt;
http://mercury.it.swin.edu.au/swinbrain/index.php/CodeSyntaxHighlight_MediaWiki_Extension&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Haven&amp;#039;t updated help page yet.&lt;br /&gt;
&lt;br /&gt;
The default color codes for Geishi could be improved.&lt;br /&gt;
&lt;br /&gt;
I have changed the colors for oobas, but am not sure what colors to assign for C. I haven&amp;#039;t managed to mimick the BASIC IDE as I don&amp;#039;t understand why keywords like &amp;quot;for&amp;quot; are blue but &amp;quot;msgbox&amp;quot; is green.&lt;br /&gt;
&lt;br /&gt;
For those that have access to the server the files are in:&lt;br /&gt;
ooodata/www/mwiki/extensions/CodeSyntaxHighlight/geshi&lt;br /&gt;
and look like (initial comments removed):&lt;br /&gt;
&amp;lt;code&amp;gt;[php]&lt;br /&gt;
$language_data = array (&lt;br /&gt;
	&amp;#039;LANG_NAME&amp;#039; =&amp;gt; &amp;#039;C&amp;#039;,&lt;br /&gt;
	&amp;#039;COMMENT_SINGLE&amp;#039; =&amp;gt; array(1 =&amp;gt; &amp;#039;//&amp;#039;, 2 =&amp;gt; &amp;#039;#&amp;#039;),&lt;br /&gt;
	&amp;#039;COMMENT_MULTI&amp;#039; =&amp;gt; array(&amp;#039;/*&amp;#039; =&amp;gt; &amp;#039;*/&amp;#039;),&lt;br /&gt;
	&amp;#039;CASE_KEYWORDS&amp;#039; =&amp;gt; GESHI_CAPS_NO_CHANGE,&lt;br /&gt;
	&amp;#039;QUOTEMARKS&amp;#039; =&amp;gt; array(&amp;quot;&amp;#039;&amp;quot;, &amp;#039;&amp;quot;&amp;#039;),&lt;br /&gt;
	&amp;#039;ESCAPE_CHAR&amp;#039; =&amp;gt; &amp;#039;\\&amp;#039;,&lt;br /&gt;
	&amp;#039;KEYWORDS&amp;#039; =&amp;gt; array(&lt;br /&gt;
		1 =&amp;gt; array(&lt;br /&gt;
			&amp;#039;if&amp;#039;, &amp;#039;return&amp;#039;, &amp;#039;while&amp;#039;, &amp;#039;case&amp;#039;, &amp;#039;continue&amp;#039;, &amp;#039;default&amp;#039;,&lt;br /&gt;
			&amp;#039;do&amp;#039;, &amp;#039;else&amp;#039;, &amp;#039;for&amp;#039;, &amp;#039;switch&amp;#039;, &amp;#039;goto&amp;#039;&lt;br /&gt;
			),&lt;br /&gt;
		2 =&amp;gt; array(&lt;br /&gt;
			&amp;#039;null&amp;#039;, &amp;#039;false&amp;#039;, &amp;#039;break&amp;#039;, &amp;#039;true&amp;#039;, &amp;#039;function&amp;#039;, &amp;#039;enum&amp;#039;, &amp;#039;extern&amp;#039;, &amp;#039;inline&amp;#039;&lt;br /&gt;
			),&lt;br /&gt;
		3 =&amp;gt; array(&lt;br /&gt;
			&amp;#039;printf&amp;#039;, &amp;#039;cout&amp;#039;&lt;br /&gt;
			),&lt;br /&gt;
		4 =&amp;gt; array(&lt;br /&gt;
			&amp;#039;auto&amp;#039;, &amp;#039;char&amp;#039;, &amp;#039;const&amp;#039;, &amp;#039;double&amp;#039;,  &amp;#039;float&amp;#039;, &amp;#039;int&amp;#039;, &amp;#039;long&amp;#039;,&lt;br /&gt;
			&amp;#039;register&amp;#039;, &amp;#039;short&amp;#039;, &amp;#039;signed&amp;#039;, &amp;#039;sizeof&amp;#039;, &amp;#039;static&amp;#039;, &amp;#039;string&amp;#039;, &amp;#039;struct&amp;#039;,&lt;br /&gt;
			&amp;#039;typedef&amp;#039;, &amp;#039;union&amp;#039;, &amp;#039;unsigned&amp;#039;, &amp;#039;void&amp;#039;, &amp;#039;volatile&amp;#039;, &amp;#039;wchar_t&amp;#039;&lt;br /&gt;
			),&lt;br /&gt;
		),&lt;br /&gt;
	&amp;#039;SYMBOLS&amp;#039; =&amp;gt; array(&lt;br /&gt;
		&amp;#039;(&amp;#039;, &amp;#039;)&amp;#039;, &amp;#039;{&amp;#039;, &amp;#039;}&amp;#039;, &amp;#039;[&amp;#039;, &amp;#039;]&amp;#039;, &amp;#039;=&amp;#039;, &amp;#039;+&amp;#039;, &amp;#039;-&amp;#039;, &amp;#039;*&amp;#039;, &amp;#039;/&amp;#039;, &amp;#039;!&amp;#039;, &amp;#039;%&amp;#039;, &amp;#039;^&amp;#039;, &amp;#039;&amp;amp;&amp;#039;, &amp;#039;:&amp;#039;&lt;br /&gt;
		),&lt;br /&gt;
	&amp;#039;CASE_SENSITIVE&amp;#039; =&amp;gt; array(&lt;br /&gt;
		GESHI_COMMENTS =&amp;gt; true,&lt;br /&gt;
		1 =&amp;gt; false,&lt;br /&gt;
		2 =&amp;gt; false,&lt;br /&gt;
		3 =&amp;gt; false,&lt;br /&gt;
		4 =&amp;gt; false,&lt;br /&gt;
		),&lt;br /&gt;
	&amp;#039;STYLES&amp;#039; =&amp;gt; array(&lt;br /&gt;
		&amp;#039;KEYWORDS&amp;#039; =&amp;gt; array(&lt;br /&gt;
			1 =&amp;gt; &amp;#039;color: #b1b100;&amp;#039;,&lt;br /&gt;
			2 =&amp;gt; &amp;#039;color: #000000; font-weight: bold;&amp;#039;,&lt;br /&gt;
			3 =&amp;gt; &amp;#039;color: #000066;&amp;#039;,&lt;br /&gt;
			4 =&amp;gt; &amp;#039;color: #993333;&amp;#039;&lt;br /&gt;
			),&lt;br /&gt;
		&amp;#039;COMMENTS&amp;#039; =&amp;gt; array(&lt;br /&gt;
			1 =&amp;gt; &amp;#039;color: #808080; font-style: italic;&amp;#039;,&lt;br /&gt;
			2 =&amp;gt; &amp;#039;color: #339933;&amp;#039;,&lt;br /&gt;
			&amp;#039;MULTI&amp;#039; =&amp;gt; &amp;#039;color: #808080; font-style: italic;&amp;#039;&lt;br /&gt;
			),&lt;br /&gt;
		&amp;#039;ESCAPE_CHAR&amp;#039; =&amp;gt; array(&lt;br /&gt;
			0 =&amp;gt; &amp;#039;color: #000099; font-weight: bold;&amp;#039;&lt;br /&gt;
			),&lt;br /&gt;
		&amp;#039;BRACKETS&amp;#039; =&amp;gt; array(&lt;br /&gt;
			0 =&amp;gt; &amp;#039;color: #66cc66;&amp;#039;&lt;br /&gt;
			),&lt;br /&gt;
		&amp;#039;STRINGS&amp;#039; =&amp;gt; array(&lt;br /&gt;
			0 =&amp;gt; &amp;#039;color: #ff0000;&amp;#039;&lt;br /&gt;
			),&lt;br /&gt;
		&amp;#039;NUMBERS&amp;#039; =&amp;gt; array(&lt;br /&gt;
			0 =&amp;gt; &amp;#039;color: #cc66cc;&amp;#039;&lt;br /&gt;
			),&lt;br /&gt;
		&amp;#039;METHODS&amp;#039; =&amp;gt; array(&lt;br /&gt;
			1 =&amp;gt; &amp;#039;color: #202020;&amp;#039;,&lt;br /&gt;
			2 =&amp;gt; &amp;#039;color: #202020;&amp;#039;&lt;br /&gt;
			),&lt;br /&gt;
		&amp;#039;SYMBOLS&amp;#039; =&amp;gt; array(&lt;br /&gt;
			0 =&amp;gt; &amp;#039;color: #66cc66;&amp;#039;&lt;br /&gt;
			),&lt;br /&gt;
		&amp;#039;REGEXPS&amp;#039; =&amp;gt; array(&lt;br /&gt;
			),&lt;br /&gt;
		&amp;#039;SCRIPT&amp;#039; =&amp;gt; array(&lt;br /&gt;
			)&lt;br /&gt;
		),&lt;br /&gt;
	&amp;#039;URLS&amp;#039; =&amp;gt; array(&lt;br /&gt;
		1 =&amp;gt; &amp;#039;&amp;#039;,&lt;br /&gt;
		2 =&amp;gt; &amp;#039;&amp;#039;,&lt;br /&gt;
		3 =&amp;gt; &amp;#039;http://www.opengroup.org/onlinepubs/009695399/functions/{FNAME}.html&amp;#039;,&lt;br /&gt;
		4 =&amp;gt; &amp;#039;&amp;#039;&lt;br /&gt;
		),&lt;br /&gt;
	&amp;#039;OOLANG&amp;#039; =&amp;gt; true,&lt;br /&gt;
	&amp;#039;OBJECT_SPLITTERS&amp;#039; =&amp;gt; array(&lt;br /&gt;
		1 =&amp;gt; &amp;#039;.&amp;#039;,&lt;br /&gt;
		2 =&amp;gt; &amp;#039;::&amp;#039;&lt;br /&gt;
		),&lt;br /&gt;
	&amp;#039;REGEXPS&amp;#039; =&amp;gt; array(&lt;br /&gt;
		),&lt;br /&gt;
	&amp;#039;STRICT_MODE_APPLIES&amp;#039; =&amp;gt; GESHI_NEVER,&lt;br /&gt;
	&amp;#039;SCRIPT_DELIMITERS&amp;#039; =&amp;gt; array(&lt;br /&gt;
		),&lt;br /&gt;
	&amp;#039;HIGHLIGHT_STRICT_BLOCK&amp;#039; =&amp;gt; array(&lt;br /&gt;
		)&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I found this link useful for working out color codes:&lt;br /&gt;
http://www.htmlgoodies.com/tutorials/colors/article.php/3478961&lt;br /&gt;
&lt;br /&gt;
[[User:Iannz]]&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=HSQLDB:Tips_and_Tricks&amp;diff=2048</id>
		<title>HSQLDB:Tips and Tricks</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=HSQLDB:Tips_and_Tricks&amp;diff=2048"/>
		<updated>2005-11-16T21:29:23Z</updated>

		<summary type="html">&lt;p&gt;Iannz: /* How to know the version of the embedded HSQLDB? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= How to connect to a &amp;quot;normal&amp;quot; (not embedded) HSQL database? =&lt;br /&gt;
  TODO&lt;br /&gt;
&lt;br /&gt;
= How to migrate data between embedded and non-embedded HSQLDB? =&lt;br /&gt;
  TODO&lt;br /&gt;
&lt;br /&gt;
= How to know the version of the embedded HSQLDB? =&lt;br /&gt;
You can determine the version of the embedded HSQLDB engine with the following Basic macro&lt;br /&gt;
&amp;lt;code&amp;gt;[oobas]&lt;br /&gt;
Option Explicit&lt;br /&gt;
&lt;br /&gt;
Sub hsqlVersion&lt;br /&gt;
 Dim databaseURLOrRegisteredName As String&lt;br /&gt;
 databaseURLOrRegisteredName = &amp;quot;hsqldb&amp;quot;&lt;br /&gt;
  &amp;#039; adjust this string to your needs. It needs to be the name of a registered database,&lt;br /&gt;
  &amp;#039; or a complete URL&lt;br /&gt;
&lt;br /&gt;
 Dim databaseContext As Object&lt;br /&gt;
 databaseContext = createUnoService( &amp;quot;com.sun.star.sdb.DatabaseContext&amp;quot; )&lt;br /&gt;
&lt;br /&gt;
 Dim databaseDocument As Object&lt;br /&gt;
 databaseDocument = databaseContext.getByName( databaseURLOrRegisteredName )&lt;br /&gt;
&lt;br /&gt;
 Dim connection As Object&lt;br /&gt;
 connection = databaseDocument.getConnection( &amp;quot;&amp;quot;, &amp;quot;&amp;quot; )&lt;br /&gt;
&lt;br /&gt;
 MsgBox &amp;quot;product version: &amp;quot; &amp;amp; connection.getMetaData().getDatabaseProductVersion()&lt;br /&gt;
&lt;br /&gt;
 connection.close&lt;br /&gt;
End Sub&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Note that this will give you a version number such as &amp;quot;1.8.0&amp;quot;, but &amp;#039;&amp;#039;not&amp;#039;&amp;#039; &amp;quot;1.8.0.1&amp;quot;. To my best knowledge, this last digit in the HSQLDB version cannot be obtained by any means at runtime.&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
	<entry>
		<id>https://wiki.openoffice.org/w/index.php?title=MediaWiki_Configuration&amp;diff=1993</id>
		<title>MediaWiki Configuration</title>
		<link rel="alternate" type="text/html" href="https://wiki.openoffice.org/w/index.php?title=MediaWiki_Configuration&amp;diff=1993"/>
		<updated>2005-11-16T01:20:17Z</updated>

		<summary type="html">&lt;p&gt;Iannz: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This pages have been automatically generated by twiki2mediawiki. Please&lt;br /&gt;
review all of them, as there will be broken markup and broken links.&lt;br /&gt;
&lt;br /&gt;
Please review your page and move the link from the &amp;quot;Converted Pages&amp;quot; to &amp;quot;Reviewed Pages&amp;quot;. To move your page to a new name you have to login. If you would like to see a page removed add a link to the [[Twiki2mediawiki_TODO_list#remove.28d.29|remove(d)]] section.&lt;br /&gt;
&lt;br /&gt;
== Reviewed Pages ==&lt;br /&gt;
&lt;br /&gt;
=== ok ===&lt;br /&gt;
&lt;br /&gt;
* [[OOo Ergonomics]] (from [[Main_OOoAnnoyances]])&lt;br /&gt;
* [[OpenDocument]]&lt;br /&gt;
* [[OpenOffice]]&lt;br /&gt;
* [[Main_IRCCommunication]]&lt;br /&gt;
* [[Main_OOoJava]]&lt;br /&gt;
* [[OOoRelease201]]&lt;br /&gt;
* [[ProductRelease]]&lt;br /&gt;
* [[Main_OOoRelease200]]&lt;br /&gt;
&lt;br /&gt;
SVG* got re-worked by Haui&lt;br /&gt;
* [[Main_SVGGroupOpacity]]&lt;br /&gt;
* [[Main_SVGEllipticArcs]]&lt;br /&gt;
* [[Main_SVGImportFilter]]&lt;br /&gt;
* [[Main_SVGSupportedFeatures]]&lt;br /&gt;
* [[Main_SVGUnsupportedFeatures]]&lt;br /&gt;
* [[Main_SVGFilterSourceCode]]&lt;br /&gt;
* [[Main_SVGUserExperiences]]&lt;br /&gt;
* [[Main_SVGPathSemantics]]&lt;br /&gt;
* [[Main_SVGHEAD]]&lt;br /&gt;
* [[Main_SVGImportTodo]]&lt;br /&gt;
* [[Main_SVGCoordinateSystems]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== remove(d) ===&lt;br /&gt;
&lt;br /&gt;
Please add a link to pages you would like to see removed here.&lt;br /&gt;
&lt;br /&gt;
* [[_default_WebLeftBar]]&lt;br /&gt;
* [[_default_WebRss]]&lt;br /&gt;
* [[Main_CaioTiago]]&lt;br /&gt;
* [[Main_OOo]]&lt;br /&gt;
* [[Main_EikeRathke]]&lt;br /&gt;
* [[Main_IanNz]]&lt;br /&gt;
* [[Main_JacquelineMcNally]]&lt;br /&gt;
* [[Main_LondonOffice]]&lt;br /&gt;
* [[Main_OfficeLocations]]&lt;br /&gt;
* [[Main_SanJoseOffice]]&lt;br /&gt;
* [[Main_StefanTaxhet]]&lt;br /&gt;
* [[Main_TokyoOffice]]&lt;br /&gt;
* [[Main_MichaelMeeks]]&lt;br /&gt;
* [[Sandbox_MyPlayGround]]&lt;br /&gt;
* [[Sandbox_StefanTaxhetSandbox]]&lt;br /&gt;
* [[Sandbox_WebLeftBar]]&lt;br /&gt;
* [[Sandbox_WebRss]]&lt;br /&gt;
* [[Main_WebRss]]&lt;br /&gt;
* [[Main_TestTest]]&lt;br /&gt;
* [[Main_StefanTaxhetAdmin]]&lt;br /&gt;
* [[Sandbox_SurveyServicesOpenOfficeOrg]]&lt;br /&gt;
* [[Main_TOCStyleInclude]]&lt;br /&gt;
* [[Main_CodeStyleInclude]]&lt;br /&gt;
* [[Main_DianeMackay]]&lt;br /&gt;
&lt;br /&gt;
== Converted Pages - pending re-work ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s good if you rename these pages as they are re-worked to remove the &amp;#039;Main_&amp;#039; suffix - use the &amp;#039;move&amp;#039; tab to do that.&lt;br /&gt;
&lt;br /&gt;
* [[DomainDeveloper]]&lt;br /&gt;
* [[Main_SurveyServicesOpenOfficeOrg]]&lt;br /&gt;
* [[Main_WebLeftBar]]&lt;br /&gt;
* [[Main_MacOSXBuildInstructions]]&lt;br /&gt;
* [[Main_ReleaseMilestone]]&lt;br /&gt;
* [[Main_ReleaseCodeline]]&lt;br /&gt;
* [[Main_TargetMilestone]]&lt;br /&gt;
* [[Main_WarningFree]]&lt;br /&gt;
* [[Main_OOoES]]&lt;br /&gt;
* [[Main_OOoBanners]]&lt;br /&gt;
* [[Sandbox_OOoInActionCompetition]]&lt;br /&gt;
&lt;br /&gt;
== Personal Pages ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s probable that we don&amp;#039;t want / require personal pages in the wiki. Hence this lot can be axed in a week or two if no-one screams, many of them contain broken Twiki junk.&lt;br /&gt;
&lt;br /&gt;
* [[Main_AlanKatzman]]&lt;br /&gt;
* [[Main_AlexandroColorado]]&lt;br /&gt;
* [[Main_AlexBrooks]]&lt;br /&gt;
* [[Main_AndreSchnabel]]&lt;br /&gt;
* [[Main_AndrewBrown]]&lt;br /&gt;
* [[Main_BadBoy]]&lt;br /&gt;
* [[Main_BerndSeidler]]&lt;br /&gt;
* [[Main_BernhardHaumacher]]&lt;br /&gt;
* [[Main_CharlesSchulz]]&lt;br /&gt;
* [[Main_ChrisReid]]&lt;br /&gt;
* [[Main_ChristophNeumann]]&lt;br /&gt;
* [[Main_CorNouws]]&lt;br /&gt;
* [[Main_CraigAdams]]&lt;br /&gt;
* [[Main_CristianDriga]]&lt;br /&gt;
* [[Main_CyrilJacquenot]]&lt;br /&gt;
* [[Main_CyrilRIP]]&lt;br /&gt;
* [[Main_DavidFraser]]&lt;br /&gt;
* [[Main_DeepankarDatta]]&lt;br /&gt;
* [[Main_DonaldGillies]]&lt;br /&gt;
* [[Main_DrewCrosland]]&lt;br /&gt;
* [[Main_EricBachard]]&lt;br /&gt;
* [[Main_EricHoch]]&lt;br /&gt;
* [[Main_ErnestoWalker]]&lt;br /&gt;
* [[Main_FlorianHeckl]]&lt;br /&gt;
* [[Main_FrankSchoenheit]]&lt;br /&gt;
* [[Main_FriedrichStrohmaier]]&lt;br /&gt;
* [[Main_GorkemCetin]]&lt;br /&gt;
* [[Main_GrSingleton]]&lt;br /&gt;
* [[Main_HelenePetit]]&lt;br /&gt;
* [[Main_JacquesRoux]]&lt;br /&gt;
* [[Main_JimWatson]]&lt;br /&gt;
* [[Main_JiriReznicek]]&lt;br /&gt;
* [[Main_JohannesSwoboda]]&lt;br /&gt;
* [[Main_JoostAndrae]]&lt;br /&gt;
* [[Main_JuergenSchmidt]]&lt;br /&gt;
* [[Main_KazunariHirano]]&lt;br /&gt;
* [[Main_KoheiYoshida]]&lt;br /&gt;
* [[Main_LaptopPerKidLetter]]&lt;br /&gt;
* [[Main_LouisSuarez]]&lt;br /&gt;
* [[Main_LuisCabreraSauco]]&lt;br /&gt;
* [[Main_MaartenBrouwers]]&lt;br /&gt;
* [[Main_MarcMaki]]&lt;br /&gt;
* [[Main_MarkoMoeller]]&lt;br /&gt;
* [[Main_MarkusHibbetts]]&lt;br /&gt;
* [[Main_MartinTaylor]]&lt;br /&gt;
* [[Main_MikeStockman]]&lt;br /&gt;
* [[Main_OpenTiss]]&lt;br /&gt;
* [[Main_PaoloMantovani]]&lt;br /&gt;
* [[Main_PatrickBall]]&lt;br /&gt;
* [[Main_PaulWujek]]&lt;br /&gt;
* [[Main_PavelJanik]]&lt;br /&gt;
* [[Main_PeteBedingfield]]&lt;br /&gt;
* [[Main_PeterEberlein]]&lt;br /&gt;
* [[Main_PeterThoeny]]&lt;br /&gt;
* [[Main_RalfSchellenberger]]&lt;br /&gt;
* [[Main_ReneAuberger]]&lt;br /&gt;
* [[Main_RobertRees]]&lt;br /&gt;
* [[Main_RolfMeyer]]&lt;br /&gt;
* [[Main_ScottCarr]]&lt;br /&gt;
* [[Main_SeoCoolhuoquoz]]&lt;br /&gt;
* [[Main_SettanttaOo]]&lt;br /&gt;
* [[Main_StephanBergmann]]&lt;br /&gt;
* [[Main_SuperBiskit]]&lt;br /&gt;
* [[Main_SvanteSchubert]]&lt;br /&gt;
* [[Main_Syndication]]&lt;br /&gt;
* [[Main_TheTschaena]]&lt;br /&gt;
* [[Main_VincentPatrick]]&lt;br /&gt;
* [[Sandbox_AndrewBrownSandbox]]&lt;br /&gt;
* [[Sandbox_BernhardHaumacherSandbox]]&lt;br /&gt;
* [[Sandbox_CristianDrigaSandbox]]&lt;br /&gt;
* [[Sandbox_ScottCarrSandbox]]&lt;br /&gt;
&lt;br /&gt;
== Managing Rights ==&lt;br /&gt;
&lt;br /&gt;
* sysop via db&amp;lt;br&amp;gt;&lt;br /&gt;
http://meta.wikimedia.org/wiki/Setting_user_rights_in_MediaWiki#Granting_rights_to_users&lt;br /&gt;
&lt;br /&gt;
* [http://meta.wikimedia.org/wiki/User_rights User Rights]&lt;br /&gt;
&lt;br /&gt;
It seems neccessary to require users to login to edit.&amp;lt;br&amp;gt;&lt;br /&gt;
This avoids defacement and makes authors feel more responsible for&lt;br /&gt;
the content.&lt;br /&gt;
&lt;br /&gt;
Special Pages to take care of:&lt;br /&gt;
* Special:Userrights&lt;br /&gt;
* OOoWiki:Administrators&lt;br /&gt;
&lt;br /&gt;
== Help Content (done) ==&lt;br /&gt;
&lt;br /&gt;
Help:Contents with links to &amp;lt;br&amp;gt;&lt;br /&gt;
http://meta.wikimedia.org/wiki/MediaWiki_FAQ &amp;lt;br&amp;gt;&lt;br /&gt;
http://meta.wikimedia.org/wiki/MediaWiki_User%27s_Guide&lt;br /&gt;
&lt;br /&gt;
Help:Editing with links to &amp;lt;br&amp;gt;&lt;br /&gt;
http://meta.wikimedia.org/wiki/Help:Editing &amp;lt;br&amp;gt;&lt;br /&gt;
http://meta.wikimedia.org/wiki/Help:Contents#For_editors&lt;br /&gt;
&lt;br /&gt;
== Copyrights (done) ==&lt;br /&gt;
&lt;br /&gt;
[[Project:Copyrights]]&lt;br /&gt;
&lt;br /&gt;
== Navigation Box (done) ==&lt;br /&gt;
&lt;br /&gt;
See http://meta.wikimedia.org/wiki/MediaWiki_FAQ#In_version_1.5&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[MediaWiki:Sidebar]]&lt;br /&gt;
&lt;br /&gt;
== InterWiki Links ==&lt;br /&gt;
&lt;br /&gt;
http://meta.wikimedia.org/wiki/Help:Guide_for_system_administrators_for_setting_up_interwiki_linking#add_your_own_custom&lt;br /&gt;
&lt;br /&gt;
[[User:Haui]] configured issue InterWiki links for TWiki. That would be handy here too.&lt;br /&gt;
&lt;br /&gt;
== Custom Namespaces ==&lt;br /&gt;
&lt;br /&gt;
http://meta.wikimedia.org/wiki/Help:Custom_namespaces&lt;br /&gt;
&lt;br /&gt;
== Cleanup Test Installations ==&lt;br /&gt;
&lt;br /&gt;
mediawiki2, mediawiki, backups of httpd.conf, ... can be purged.&lt;br /&gt;
&lt;br /&gt;
We might want to keep one playground though.&lt;br /&gt;
&lt;br /&gt;
== CodeSyntaxHighlight MediaWiki Extension ==&lt;br /&gt;
Code Syntax highlighting using GeShi&lt;br /&gt;
http://qbnz.com/highlighter/&lt;br /&gt;
Has been added as per&lt;br /&gt;
http://mercury.it.swin.edu.au/swinbrain/index.php/CodeSyntaxHighlight_MediaWiki_Extension&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Haven&amp;#039;t updated help page yet.&lt;br /&gt;
[[User:Iannz]]&lt;/div&gt;</summary>
		<author><name>Iannz</name></author>
	</entry>
</feed>