AUTHOR'S MAIN SITE   > > > > >   TABLE OF CONTENTS for Open Office database tutorials.   > > > > >   MACROS section, Open Office tutorials.

Open Office Tutorials
Document Properties

This page is one of several trying to help you get the most out of the splendid Open Office. They are allied with a larger set concentrating on ooBase.

Remember that Open Office, including ooBase, is free! But don't let that fool you. And it's not new. Big organizations, government and civilian, are adopting it as their standard office suite... and saving million$, and still Getting The Job Done.

There's more about ooBase in the main index to this material.

This page is "browser friendly". Make your browser window as wide as you want it. The text will flow nicely for you. It is easier to read in a narrow window. With most browsers, pressing plus, minus or zero while the control key (ctrl) is held down will change the texts size. (Enlarge, reduce, restore to default, respectively.) (This is more fully explained, and there's another tip, at my Power Browsing page.)

Page contents © TK Boyd, Sheepdog Software ®, 2/06-6/09.



Introduction

This page is one of a group about using macros in Open Office... a topic I am learning about, shedding much blood sweat and tears along the way! It raises almost as many questions as it gives answers. It also has a very limited objective. If you are getting started with macros, or want less "Here be Terra Incognita", then I'd suggest that you start with my Introduction to OOP, Events and Macros.

In this tutorial, I explore looking at a document's properties, with some thoughts on the Open Office programming documentation along the way.

This tutorial was written using ooBase version 3.0 on Windows XP, but many things should work the same way under other post version 1 OpenOffice installations, and under other operating systems. There are some strong reasons to move to Open Office 3.1 if you want to use macros with ooBase. Where the difference is important, you will be told.


Where we've come from....

Some Gentle Readers will have come here from a Google search. Others will have read my first tutorial on creating a macro for doing a data backup chore. In that tutorial, we deleted a file and copied another... but they both had to be in the computer's root directory, as did the document holding the macro. In this essay, we are going to go beyond that. The document and macro presented in this tutorial can do the data backup on files in the document's directory... regardless of where that is. ("Directory"="folder", by the way.)

You don't need to check out the earlier tutorial just yet, though.


Preliminary play....

Set up a folder. You can call it what you like, put it where you like.

If what follows in the next paragraph is "too rich" for your current set of skills, read my introduction to macro programming, where you will be taken through such things more gently.

Create an ooWriter document in the folder you just created. Call it "OpOf6DocProps", to match the filename of this tutorial. (Although you could give it another name.) Create a macro container called "OpOf6DocP", and in it create a macro called RotateFiles2. Make it the handler for "mouse button pressed" for a button on your document. For the moment, the macro container merely holds....

REM  *****  BASIC  *****

Sub RotateFiles2
MsgBox "Getting started"
End Sub

... and clicking the button merely puts "Getting Started" up in a message box.

Once that's working, change the macro to....

Sub RotateFiles2
MsgBox thisComponent.url
End Sub

When I ran that, I got the following in a message box....

file:///C:/Documents%20and%20Settings/
Tom/My%20Documents/Databases/
Macro3/OpOf6DocProps.odt

You should, if you named your document as I told you to, also get something starting with file:/// and ending with OpOf6DocProps.odt... but what you get in between will depend on where your folder for this work is. I hope you can see the connection between what thisComponent.url gives you and where you stored the document, though?


The magic "thisComponent"....

Your understanding of the wonderful "thisComponent" begins by thinking of it as a variable. But it is a variable that you don't need to have a Dim statement for, and which you don't have to fill yourself. It will always (? I think!) hold the last previously active document... which if your macro is saved in an ooWriter document (or other, e.g. ooCalc sheet, I think) will be that document (or sheet).

If you look for information on thisComponent in the Open Office online documentation, you may get the search result I got... 89 hits. Digging around by other means brought me to a page with a helpful(?) section in it.

But I wasn't ready to understand quite what that was saying, so I'll return to my exposition of what I do understand about thisComponent.

As I said... it is like a variable. In it is a document object. If you execute....

MsgBox thisComponent.url

... you will be rewarded with a pop up giving the name and location of the current document.

"URL" seems to be a property of the document.

Judging from things you can see on the internet, there are sundry methods that can be called with phrases like....

oCurSelection = thisComponent.getCurrentSelection()

... but those are "matters which are too high for me" at the moment. But I bet pushing back that boundary of my ignorance is going to yield succulent fruit when I can get to it.


Putting "thisComponent.url" to work....

For the next several column inches, we are going to put thisComponent.url to work in the context of the data backup task. If you don't feel you need that, you can skip ahead to further discussion of document properties, etc.

First I will recap what the macro we are working on will do. It will help you guard against data loss by allowing you to maintain simply three versions of some file. Let's say you keep the most current version in a file called "GoodStuff". And let's say that your next older version is called "GoodStuffDad", and the oldest version you have is called "GoodStuffGrandad".

From time to time, the macro will....

In our first attempt at this macro, we achieved all of that... but it would only work if the files were in the root directory (C:/ on a Windows machine)

The code that follows is the same as our earlier code, except we added a "Dim iCount As Integer", and the line....

sPathToFile="C:/"

.... has been replaced by....

'=====
REM: Here, in the "only works in root version",
'  we had: sPath="C:/"

REM start with...

sPath = thisComponent.url

REM First note that while in many parts of OO
'  the punctuation mark for separating folders
'  is a forward slash (/), the result of a
'  ConvertFromURL, on a Windows machine is a
'  backslash (\). So we will strip off "stuff" from
'  the right hand end of the path+name until we reach
'  a "/". THEN we will use ConvertFromURL.
'  This can be done more cleverly, but what follows
'  is (?) clear. It can also be done more "robustly"... it
'  will fail if it is passed unexpected strings, e.g.
'  one with no / in it.
'The point is to change, say, file:///C:/MyDocs/Good.txt
'  to  file:///C:/MyDocs/, the "path" part of the URL.

iCount= Len(sPath)-1
Do While Right(sPath,1)<>"/"
  sPath=Left(sPath,iCount)
  iCount=iCount-1
  loop

REM file:///C:/MyDocs/Good.txt now stripped down to file:///C:/Mydocs/

sPath= ConvertFromURL(sPath)

REM End of new "sPath=" code
'=====

For your convenience, the full macro will be provided in a moment, but first I want to discuss the replacement code, which I just showed you.

Most of what you need to know has been incorporated into the code as REMarks.

The command iCount=Len(sPath)-1 fills the variable iCount, which we created, with a number. It checks how many characters are in the string being held in sPath (another variable we created, and filled a moment ago), minus 1. During the While loop (which we will come to), what's in iCount is repeatedly reduced by 1. Len is a function built into ooBasic.

The ooBasic "Right" function gives you a number of characters from the right hand end of a string. Right("abcde",2) gives you "de", Right("abcde",3) gives you "cde", etc.

During the While loop, we do two things, assuming that Right(sPath,1) does not yet equal "/". We....

So far, we have been working with what ooBase returns when you ask for thisComponent.URL. It will be in the form....

file:///C:/Documents/Macro3/GoodStuff.txt

The function ConvertFromURL changes that slightly, converting it to the right form for our needs when we come to use Kill and Name and FileCopy

And that's it!

As promised, here is the macro in full, so you don't need to "assemble" the revised version....

REM  *****  BASIC  *****

REM See....
'http://sheepdogguides.com/fdb/opof6docprops.htm
'... for full details

Dim sPath as string
Dim iCount As integer

Sub RotateFiles2

Dim sGFFilename,sFFilename,sSFilename,_
   sPath as string

'=====
REM: Here, in the "only works in root version",
'  we had: sPath="C:/"

REM start with...

sPath = thisComponent.url

REM First note that while in many parts of OO
'  the punctuation mark for separating folders
'  is a forward slash (/), the result of a
'  ConvertFromURL, on a Windows machine is a
'  backslash (\). So we will strip off "stuff" from
'  the right hand end of the path+name until we reach
'  a "/". THEN we will use ConvertFromURL.
'  This can be done more cleverly, but what follows
'  is (?) clear. It can also be done more "robustly"... it
'  will fail if it is passed unexpected strings, e.g.
'  one with no / in it.
'The point is to change, say, file:///C:/MyDocs/Good.txt
'  to  file:///C:/MyDocs/, the "path" part of the URL.

iCount= Len(sPath)-1
Do While Right(sPath,1)<>"/"
  sPath=Left(sPath,iCount)
  iCount=iCount-1
  loop

REM file:///C:/MyDocs/Good.txt now stripped down to file:///C:/Mydocs/

sPath= ConvertFromURL(sPath)

REM End of new "sPath=" code
'=====

sGFFilename="GoodStuffGrandfather.txt"
sFFilename="GoodStuffDad.txt"
sSFilename="GoodStuff.txt"

If FileExists(sPath+sGFFilename) Then
  Kill(sPath+sGFFilename)
  REM BEWARE: "Kill" will do just that to a file... with
  ' no "Are you sure?" confirmation step. And it won't
  ' be in the recycle bin, either.
  MsgBox("File "+sGFFilename+" deleted")
End If

If FileExists(sPath+sFFilename) Then
  Name sPath+sFFilename As sPath+sGFFilename
     'The use of "As" in the previous has nothing to do with a Dim
     '... and yes, you do need to specify the path for both
  REM BEWARE: If file is open in another OO window, you'll get
  '  a message saying "File not found".... not the most helpful
  '  error message!
  'It would be nice if I could discover an "Is it open?" test,
  '  to use as the FileExists test was used. Sigh.
  MsgBox("File "+sGFilename+" copied to make new "+sGFFilename)
  Else
  MsgBox("There was no '"+_
     sFFilename+"' to make new '"+sGFFilename+"' from")
     'You can't, by the way, put a split inside an
     'explicit string. Won't work:
     '   MsgBox("Split in _
     '       string.")
     'But will work:
     '   MsgBox("Split in "+_
     '       "string.")
End If

If FileExists(sPath+sSFilename) Then
  FileCopy (sPath+sSFilename, sPath+sFFilename)
  MsgBox("File "+sSFilename+" copied, overwriting old "+sFFilename)
  Else
  MsgBox("There was no '"+_
     sSFilename+"' to make new '"+sFFilename+"' from")
End If

MsgBox("File Grandfather/Father/Son job done.")

End Sub

It looks a little scary at first, but it is okay if you take it a bit at a time. Deriving it from scratch was a little hairy, but I think what I've learnt along the way will facilitate the next project. I certainly hope so.


Other properties....

So... we have seen how to get at, and one use for, a document's URL property. What about other properties?

When I finally discovered that I could say thisComponent.url, I was much heartened, because I'd already seen the page about MediaDescriptor, and one of the properties of the MediaDescriptor service ("object", in my terms) was "URL". Another property was "Author". I didn't particularly care to know the author of the document I was looking at, but I tried....

MsgBox thisComponent.Author

... in hopes (expectations!) that I could find what was in this document's MediaDescriptor "Author" property. No joy. "BASIC runtime error. Property or method not found." Sigh. (You may need to click the "Okay" of the error message's box several times to clear it.) It seems that while the "URL" property of thisComponent looks to be the same thing as the MediaDescriptor URL property, not all of the MediaDescriptor properties are available through thisComponent. So how are the other properties accessed? I wish I knew!

The following works, for what it is worth....

Dim oThingie as object

Sub Experiment
oThingie=thisComponent
MsgBox oThingie.url
End Sub

... but change the central line to....

MsgBox oThingie.MediaDescriptor.url

... and you're back to "Property or method not found.". When I figure out how to use the object (service), I suspect some of its properties are going to be useful. Maybe by then I will have found a way to look up the methods of MediaDescriptor, too! I live in hope.

The MediaDescriptor service is described at this page in the API guide.

Oh well. We've made some progress in this tutorial!


OpenOffice documentation....

The documentation can be extremely frustrating. I am still unable to navigate it easily. Also, searches for things which I know are present, e.g. "ConvertFromURL", fail to find the excellent relevant pages.

You can try using something like...

site:wiki.services.openoffice.org ConvertFromURL

... as a Goggle search string. It turned up the right page... along with 8 other hits.

* Guide to ooBasic.... the language of Open Office macros...

The OpenOffice.org page where the ooBasic guide starts. The flawed search engine remains a problem. You may find that digging in the "Runtime library" section turns up Good Stuff, depending on what you are looking for. (A lot of what I wanted was there.)

* Guide to OO API.... the "things" Open Office is built from, e.g. getByName. They (I'm pretty sure) underlie all of Open Office. How you get to them, directly, with ooBasic I'm not so sure about.

The "things" include what I would call objects, methods and properties. The nice people at Open Office use the term "service" for some things I think of... quite possibly ignorantly... as objects. Not everything I call an object is a service. Some of the things I call methods they call functions. We both use "property" the same way... I think! The API guide also tells you about other useful things. If you want to become a skilled OpenOffice programmer, it would probably be very wise to attempt to master "What is a thingie", where "thingie" can equal...

Don't be overwhelmed by that list. It really isn't as bad as it seems.

The Guide is at this OpenOffice.org page

* Creating, saving, loading documents... Although the following is "just" a discussion within oooForum.org, it incorporates a commendable tutorial which takes you through the basics. An excellent introduction.

oooForum.org essay on basic document operations.


Odds and ends....

Here follows a "bad" section of bits and pieces which might lead you to Good Stuff... but it isn't well organized, etc. You might want to skip over this section to the next section where I present one last bit of code, which has some curious elements.

============================

Here's a possibly helpful quote from an oooForum.org discussion.....

Service DocumentInfo is deprecated from version 3.1. (In a note in the api.openoffice.org documentation.)

It is replaced by service DocumentProperties, and interface XDocumentProperties.

Example of display:

Option Explicit

Sub DisplayUserFields
Dim udefProps As Object, allUProps As Object, oneUProp As Object
Dim UPlist As String

udefProps = ThisComponent.DocumentProperties.UserDefinedProperties
allUProps = udefProps.PropertyValues
UPlist = ""
For Each oneUProp in allUProps
  if IsUnoStruct(oneUProp.Value)  then
    With oneUProp.Value
      UPlist = UPlist & oneUProp.Name & " = " & _
      DateSerial(.Year, .Month, .Day) & chr(13)
    End With
  else
    UPlist = UPlist & oneUProp.Name & " = " & oneUProp.Value & chr(13)
  end if
Next
MsgBox(UPlist, 0, "User Defined Properties")
End Sub

The variable allUProps is an array of structures com.sun.star.beans.PropertyValue. A user property of type date in the user interface is in fact a structure com.sun.star.util.DateTime. Other data types are directly converted to string by the macro.

============================

Here's a snippet which might help you explore thisComponent further. I suspect that for this to work, your ooWriter document needs a section named "Instructions".

This untested snippet was lifted from..... an oooForum.org discussion

Dim oDoc as Object
   Dim oSections as Object
   Dim oSec as Object

   oDoc = thisComponent
   oSections = oDoc.getTextSections
   oSec = oSections.GetByName("Instructions")
   oSec.Anchor.String = "Hello"

============================


Footnote....

In the course of writing this tutorial, I had MsgBox thisComponent.url putting a complex string on the screen, but, short of doing a screen grab and presenting it as a graphic, I couldn't copy the text. In order to present that text, I wrote the following odd little macro.

Some will find what I've done "elegant", others will say that it is "bad". What do you think? (It does work!)

Dim oThingie as object

Sub URLtoTextBox
oThingie=thisComponent.getdrawpage()_
.getforms()_
.getbyname("Standard")_
.getbyname("TextBox")
oThingie.text=thiscomponent.url
End Sub

The "_"s at the ends of several lines allow us to put what is "one line" as far as the program is concerned onto several screen lines. You can't put them "just anywhere". And you can't introduce spaces, for instance at the start of lines to indent material. If you think your trouble is stemming from use of the underscores, put the whole line on a single screen line, get it working like that, and then break it up to facilitate reading the code on your screen.

A tiresome detail: If you are using OpenOffice 3.1, that should work. If you are using OpenOffice 3.2, change the last part of the....

.getByName("Standard")_

...line to....

.getByName("Form")_

... and you may well have to change the....

.getByName("TextBox")

... line. I would GUESS it becomes....

.getByName("Text Box 1")

... yes, with spaces, and a "1". Sorry about that. The good programmers at Open Office HQ rarely do such things to us... upgrading us usually painless and a Good Idea. But somethings there are Reasons.


We've done it!...

That's about it, for this tutorial. I hope it will have made you inclined to return to the main page of my Open Office tutorials, and access another. The tutorial you are looking at is very untypical of the pages on my site... I don't usually drag my poor readers through areas of my ignorance... but I hope you've had a few of your dark corners filled with light. I've been talking about important subjects, I strongly suspect... even if I've spoken imperfectly. If anyone wants to write in and "educate" me, they are more than welcome to do so!





Editorial Philosophy

I dislike 'fancy' websites with more concern for a flashy appearance than for good content. For a pretty picture, I can go to an art gallery. Of course, an attractive site WITH content deserves praise... as long as that pretty face doesn't cost download time. In any case....

I am trying to present this material in a format which makes it easy for you to USE it. There are two aspects to that: The way it is split up, and the way it is posted. See the main index to this material for more information about the way it is split up, and the way it is posted.


Ad from page's editor: Yes.. I do enjoy compiling these things for you... I hope they are helpful. However.. this doesn't pay my bills!!! If you find this stuff useful, (and you run an MS-DOS or Windows PC) please visit my freeware and shareware page, download something, and circulate it for me? Links on your page to this page would also be appreciated!

PLEASE >>> Click here to visit editor's Sheepdog Software (tm) freeware, shareware pages <<< PLEASE


If you liked this ooBase tutorial, see the main index for information other help from the same author.

Editor's email address. Suggestions welcomed!     - - -    Want a site hosted, or email? I like 1&1's services.




Valid HTML 4.01 Transitional Page tested for compliance with INDUSTRY (not MS-only) standards, using the free, publicly accessible validator at validator.w3.org


One last bit of advice: Be sure you know all you need to about spyware.

. . . . . P a g e . . . E n d s . . . . .