Mapa conceptual: què és el Programari Lliure (PL)?

Què és el Programari Lliure? a la Viquipèdia hom pot trobar aquesta mapa conceptual que ho explica gràficament:

Com invocar una funció de calc des d’una macro?

La idea central és invocar la funció a través del servei UNO com.sun.star.sheet.FunctionAccess. Cal passar dos arguments: el nom de la funció, en anglès, que volem executar; i un Array amb els paràmetres que demana la funció.


la llista de funcions en anglès la podem trobar a la wiki: http://wiki.services.openoffice.org/wiki/Documentation/How_Tos/Calc:_Functions_listed_by_category

En l’exemple invocarem la funció BDEXTREU (DGET en anglès) que permet trobar en un rang de cel·les aquella que verifica unes determinades condicions. Els paràmetres de BDEXTREU (DGET) també els trobem a la wiki:
http://wiki.services.openoffice.org/wiki/Documentation/How_Tos/Calc:_DGET_function

En una fulla de Calc posaré els següents valors en el rang B1:D22. Aquesta serà la taula de dades:





id nom valor
1 a aa
2 b bb
3 c cc
4 d dd
5 e ee
6 f ff
7 g gg
8 h hh
9 i ii
10 j jj
11 k kk
12 l ll
13 m mm
14 n nn
15 o oo
16 p pp
17 q qq
18 r rr
19 s ss
20 t tt
21 u uu



I en el rang B24:D25 hi poso les condicions de cerca. Els títols han de coincidir amb els de la taula de dades





id nom valor
8




Poso que em cerqui el valor ID=8


Aleshores, en una altre cel·la verifico que la funció troba el valor posant:


=BDEXTREU(B1:D22;C1;B24:D25)


Que ho llegeixo així, en el rang de dades B1:D22, obté el valor de la columna de títol C1, que verifica les condicions expressades al rang B24:D25.


Les condicions que hi ha a B24:D25 són (ID=8) i (NOM pot ser qualsevol valor) i (VALOR pot ser qualsevol valor).


La funció retorna “h” com era d’esperar.


Aquesta és una funció molt útil per a fer cerques en fulles. Com puc utilitzar-la en una macro? Primer de tot, creo un nou mòdul de macros  i hi afegeixo el següent codi:



function MacroBDExtreu as String


   Dim oFuncio As Object
   Dim oFull As Object
   Dim oRangTaula As Object
   Dim oColumnaSelect As Object
   Dim oColumnaCondicions as Object
   Dim sRetorn As String

   oFull = ThisComponent.Sheets.getByName(“Full1”)


   oRangTaula = oFull.getCellRangeByName(“B1:D22”)
   oColumnaSelect = oFull.getCellByPosition(2, 0)
   oColumnaCondicions = oFull.getCellRangeByName(“B24:D25”)


   oFuncio = createUnoService(“com.sun.star.sheet.FunctionAccess”) 
   
   ‘ Invoca la funció pel seu nom en anglès: BDEXTREU –> DGET
   sRetorn = oFuncio.callFunction(“DGET”, _
                                  Array(oRangTaula, _
                                        oColumnaSelect.String, _
                                        oColumnaCondicions)) 
   
   MsgBox(sRetorn)


   MacroBDExtreu = sRetorn
End Function

I invoquem la macro que ens mostra un missatge amb la dada trobada.

Macros OOoBasic com funcions de Calc.

OpenOffice.org Calc aporta una llarga llista de funcions incorporades.

Aquesta llista, amb els noms de les funcions en anglès, la podem obtenir aquí:
http://wiki.services.openoffice.org/wiki/Documentation/How_Tos/Calc:_Functions_listed_by_category

 En alguna ocasió ens interessarà poder fer servir alguna d’aquestes funcions dins del codi d’una macro. Igualment es pot donar el cas que ens interessi invocar una macro com si fos una funció icroporada del calc.

Comencem per això últim. Invocar una macro com si fos una funció de Calc.

Per a poder invocar una macro com si fos una funció de Calc és necessari, primer de tot, que la macro estigui carregada. Per defecte es carreguen les macros que estan a la biblioteca “Standard”.

Si la macro que vull invocar es troba a un mòdul de la llibreria Standard (ja sigui del Document, o de l’usuari a “Les-meves-macros”) aleshores es pot invocar directament.

A les macros del document, a la llibreria Standar, creo un  mòdul nou Module1 i hi poso el següent codi:

Function HelloWorld()
    HelloWorld = “macro invocada com una funció”
End Function

Aleshores, a qualsevol cel·la de la fulla de càlcul hi escric

=helloworld()

en  invocar les funcions no és distingeix majúscules i minúscules

apareixerà immediatament

 macro invocada com una funció

No té gaire ciència. La clau és que la macro es trobi a la llibreria “Standard”.

Per a que quedi clar aquest punt, quan fem Eines-Macros-Organitza les macros-OpenOffice.org Basic obtenim això:

Veiem a la imatge com hi ha dues biblioteques Standard: una a “Les meves macros” i l’altre al document, que en aquest cas s’anomena “macro-funció-calc.ods”.

En tot moment puc crear noves biblioteques de macros (libraries) fent click al botó “Organitzador…”:

Des de la pestanya Biblioteques:

En la que puc triar on vull posar la biblioteca: De l’usuari, general, o del document:
En aquest document de la wiki de l’OpenOffice.org  proposen la següent tècnica per al cas que en que tinguem moltes macros i molt de codi  a les  macros. En aquesta situació, en comptes de sobrecarregar la biblioteca estàndard amb molts mòduls molt grossos, el que proposen es crear biblioteques auxiliars, aleshores, en la biblioteca Standard el que posaríem serien funcions de pont que l’únic que farien seria carregar la llibreria corresponent i invocar a la funció d’utilitat desitjada.   

Com dibuixar una escala semi-logarítmica amb OpenOffice.org Draw?

En aquest exercici dibuixo una escala semi-logarítmica. Aquesta mena de gràfiques es fan servir en tecnologia, per exemple a l’electrònica es fa servir per representar la resposta en freqüència dels circuits (els diagrames de Bode).

Aquest exercici ens servirà per aprendre com  dibuixar línies amb macros de OOoBasic.

Primer de tot, creo un nou document de Draw. I amb l’organitzador de macros creo un mòdul al document.

Faig servir aquest codi

Sub DibuixaLinia
    const cMarge = 1000
  
    Dim oPagina as Object
    Dim oLinea as Object
    Dim oPosition as Object
    Dim oSize as Object
    Dim iPagWidth as Integer
    Dim iPagHeight as Integer  
    Dim iWidth as Integer
    Dim iHeight as Integer  
    Dim v as Double
    Dim w as Double
    Dim x as Double
    Dim xx as Integer
    Dim y as Double
    Dim yy as Integer
    Dim iNumDecades as Integer
    Dim iNumVerticals as Integer

    iNumDecades = 7
    iNumVerticals = 10

    ‘ obté la pàgina de dibuix actual
    oPagina = ThisComponent.getDrawPages().getByName(“page1”)

    ‘ dimensions de la pàgina
    iPagWidth = oPagina.Width
    iPagHeight = oPagina.Height

    ‘ dimensions de l’àrea de dibuix, amb un marge de 1000px
    iWidth = oPagina.Width – (2 * cMarge)
    iHeight = oPagina.Height – (2 * cMarge)
  
    ‘ pinta escala logarítmica
    for w = 0 to (iNumDecades – 1)
        for v = 1 to 10
    x = log(v * (10 ^ w)) / log(10)
    xx = ((iWidth / iNumDecades) * x) + cMarge
     
    oLinea = ThisComponent.createInstance(“com.sun.star.drawing.LineShape”)
    oLinea.LineColor = RGB(0, 0, 255)
    oLinea.LineWidth = 2      
     
    oPosition = oLinea.Position
    oPosition.X = xx
    oPosition.Y = cMarge
    oLinea.Position = oPosition

    oSize = oLinea.Size
    oSize.Width = 0
    oSize.Height = iHeight
    oLinea.Size = oSize


    oPagina.add(oLinea)
 next
next

‘ dibuixa les divisions verticals
for w=0 to iNumVerticals
 oLinea = ThisComponent.createInstance(“com.sun.star.drawing.LineShape”)
oLinea.LineColor = RGB(0, 0, 255)
oLinea.LineWidth = 2

yy = ((iHeight / iNumVerticals) * w) + cMarge


oPosition = oLinea.Position
oPosition.X = cMarge
oPosition.Y = yy
oLinea.Position = oPosition

oSize = oLinea.Size
oSize.Width = iWidth
oSize.Height = 0
oLinea.Size = oSize

oPagina.add(oLinea)  
next
End Sub

Si executem aquesta macro, obtindrem el paper semi-logarítmic.

Una millora evident és factoritzar la funció que dibuixa la línia:
function Linea(int x, int y, int llarg, int ample, int vermell, int verd,  int blau, int gruix)
 dim oLinea as Object
 dim oPosition as Object
 dim oSize as Object

 oLinea = ThisComponent.createInstance(“com.sun.star.drawing.LineShape”)


oLinea.LineColor = RGB(vermell, verd, blau)
oLinea.LineWidth = gruix 

oPosition = oLinea.Position
oPosition.X = x
oPosition.Y = y
oLinea.Position = oPosition
oSize = oLinea.Size
oSize.Width = llarg
oSize.Height = ample
oLinea.Size = oSize

 Linea = oLinea


end sub
El resultat del programa anterior és:

ListBox a formulari de l’OpenOffice.org

El control listbox dels formularis de l’OpenOffice.org permet sel·leccionar un o diversos valors d’una llista. La llista de valors es pot carregar des d’una taula, o des d’una consulta SQL, o bé amb valors arbitraris.

Carregar la listbox des d’una taula o amb un SQL és tan senzill com ajustar les propietats corresponents del control. En canvi, per carregar valors arbitraris cal fer-ho amb BASIC.

Com sempre, estic parlant de OpenOffice 3.2 en català sobre Ubuntu Lucid Lynx 10.04.

Vet aquí l’exemple. Primer de tot obro un nou document del Writer. Hi poso els següents components:

Amb l’organitzador de macros creo una macro nova dins del document, l’edito i hi afegeixo el codi per respondre als diferents events.

En prémer el botó Afegeix>> el que faré serà que el text que està a la caixa de text Afegeix opció s’afegeixi a la listbox.

Això ho faig amb el codi següent que associo a l’event de fer click al botó.

sub AfegeixALlista
Dim oDoc as object
Dim oText as Object
Dim oLlista as Object
Dim sLlista() as String

oDoc = ThisComponent.getDrawPage().Forms().getByIndex(0)
oText = oDoc.getByName(“Text1”)
oLlista = oDoc.getByName(“Llista1”)
sLlista = oLlista.StringItemList
bas_PushArray(sLlista, oText.Text)
oLlista.StringItemList = sLlista
Deselecciona
End sub

La funció bas_pushArray redimensiona un array per incrementar-ne el nombre d’elements en u, i afegeix el nou element.


‘ La següent sub extreta de
http://www.oooforum.org/forum/viewtopic.phtml?t=38721
‘ very simple routine appending a single element to an array which
‘ may be undimensioned (LBound > UBound)

Sub bas_PushArray(xArray(),vNextElement)
Dim iUB,iLB as Integer
iLB = lBound(xArray())
iUB = uBound(xArray())
If iLB > iUB then
iUB = iLB
redim xArray(iLB To iUB)
else
iUB = iUB +1
redim preserve xArray(iLB To iUB)
endif
xArray(iUB) = vNextElement
End Sub


Per associar la sub d’afegir element a la llista a l’event de picar Return sobre el botó, faig el següent, associo la següent sub a l’event de”en prémer una tecla”, i faig que la sub rebi com argument l’event. De l’event puc determinar quina tecla s’ha premut. Si la tecla és Return, aleshores executa la sub d’afegir a la listbox.

Sub AfegeixALListaKeyPressed(Event as Object)
‘ si està fet amb return, Ok
if Event.KeyCode = com.sun.star.awt.Key.RETURN then
AfegeixALlista
end if
end sub

Un cop he afegit l’element a la listbox el que faig és deseleccionar elements. També hauria pogut fer que l’element afegit fos l’element actualment seleccionat.

Per deseleccionar faig:

Sub Deselecciona
Dim oDoc as object
Dim oLlista as Object
Dim oLlista2 as Object
Dim EmptyList()

oDoc = ThisComponent.getDrawPage().Forms().getByIndex(0)
oLlista2 = oDoc.getByName(“Llista2”)
oLlista = oDoc.getByName(“Llista1”)

oLlista.SelectedItems = EmptyList()
oLLista2.SelectedItems = EmptyList()
End Sub

Per sel·leccionar un o molts valors (en aquest cas he de posar a true la propietat de múltiples valors) puc fer servir el següent codi. que he d’associar a l’event “L’estat de l’element ha canviat” de la listbox:

Sub ObteValors
Dim oDoc as object
Dim ollista2 as Object
Dim oLlista as Object
Dim iIndex() as Integer
Dim i as integer
Dim LlistaSeleccionades()

oDoc = ThisComponent.getDrawPage().Forms().getByIndex(0)
oLlista = oDoc.getByName(“Llista1”)
ollista2 = oDoc.getByName(“Llista2”)

‘ obté els índexos de les seleccionades
iIndex = oLlista.SelectedItems

‘ buida la listbox de seleccionades
ollista2.StringItemList() = LlistaSeleccionades()

‘ Redimensiona l’array auxiliar per a poder encabir-hi els nous valors
Redim LlistaSeleccionades(uBound(iIndex()))

‘ El plena amb les noves seleccionades
for i=0 to uBound(iIndex())
LlistaSeleccionades(i) = oLlista.StringItemList(iIndex(i))
next i

‘ l’assigna a la listbox
ollista2.StringItemList = LlistaSeleccionades
End sub

Si vull eliminar algun dels valors de la llista, primer he de tenir-lo seleccionat. Si no hi ha res seleccionat, ignora la crida (Sí, hi ha un goto!). El que fa és redimensionar (redim) a un element menys, preservant-ne el contingut, i deseleccionant al final.

Sub EliminarValor
Dim oDoc as object
Dim oText as Object
Dim oLlista as Object
Dim sValorObtingut as String
Dim iIndex() as Integer
Dim sNovaLlista() as String
Dim iDimInicial as Integer
Dim iDimFinal as Integer
Dim i,j as Integer

oDoc = ThisComponent.getDrawPage().Forms().getByIndex(0)
oLlista = oDoc.getByName(“Llista1”)
‘xRay oLlista
iIndex = oLlista.SelectedItems
if UBound(iIndex()) = -1 and LBound(iIndex()) = 0 then goto SORTIR

iDimInicial = UBound(oLlista.StringItemList())
iDimFinal = iDimInicial – 1
if iDimFinal < idimfinal =” 0″ j=”0″ i=”0″> iIndex(0) then
sNovaLlista(j) = oLlista.StringItemList(i)
j= j + 1
end if
next i
oLlista.StringItemList() = sNovaLlista()
iIndex = oLlista.SelectedItems
Deselecciona
SORTIR:
End sub

Per eliminar tots, Empty Array a tot arreu i deseleccionar.

Sub EliminaTots
Dim oDoc as object
Dim oLlista as Object
Dim oLlista2 as Object
Dim EmptyList()

oDoc = ThisComponent.getDrawPage().Forms().getByIndex(0)
oLlista = oDoc.getByName(“Llista1”)
oLLista2 = oDoc.getByName(“Llista2”)

oLlista.StringItemList = EmptyList
oLLista2.StringItemList = EmptyList
Deselecciona
End sub

Finalment, puc ordenar (botons Puja i Baixa) la llista. Cal tenir un element selccionat, i si no, ignora la crida. Es tracta d’intercanviar les posicions dels elements de l’array que van seguits, i recarrregar l’array StringItemList amb el nou array reordenat.

Sub Puja
Dim oDoc as object
Dim oText as Object
Dim oLlista as Object
Dim iIndex() as Integer
Dim sAux as String
Dim EmptyList()
Dim i,j,k as Integer
Dim sNovaLlista() as String
dim sNovaLlistaSeleccionat(0) as Integer
Dim iDimLlista as integer

oDoc = ThisComponent.getDrawPage().Forms().getByIndex(0)
oLlista = oDoc.getByName(“Llista1”)
iIndex = oLlista.SelectedItems
‘ primer mira si té un element sel·leccionat
if UBound(iIndex()) = -1 and LBound(iIndex()) = 0 then goto SORTIR
‘ si el té, mira que no sigui el primer
if iIndex(0) > 0 then
‘ prepara un Array auxiliar
iDimLlista = UBound(oLlista.StringItemList())
Redim sNovaLlista(iDimLlista)

‘ obté els índexos a intercanviar
i = iIndex(0)
j = i – 1

‘ itera per carregar l’array auxiliar
for k=0 to iDimLlista
sNovaLlista(k) = oLlista.StringItemList(k)
next k

‘ intercanvia les posicions en l’array auxiliar

sAux = sNovaLlista(j)
sNovaLlista(j) = sNovaLlista(i)
sNovaLlista(i) = sAux

‘ carrega la llista

oLlista.StringItemList() = sNovaLlista()

‘ selecciona l’anterior
sNovaLlistaSeleccionat(0) = j
oLlista.SelectedItems = sNovaLlistaSeleccionat

end if
oLlista.Refresh()
SORTIR:
End sub

Sub Baixa
Dim oDoc as object
Dim oText as Object
Dim oLlista as Object
Dim iIndex() as Integer
Dim sAux as String
Dim EmptyList()
Dim i,j,k as Integer
Dim sNovaLlista() as String
dim sNovaLlistaSeleccionat(0) as Integer
Dim iDimLlista as integer

oDoc = ThisComponent.getDrawPage().Forms().getByIndex(0)
oLlista = oDoc.getByName(“Llista1”)
iIndex = oLlista.SelectedItems

‘ primer mira si té un element sel·leccionat
if UBound(iIndex()) = -1 and LBound(iIndex()) = 0 then goto SORTIR

‘ si el té, mira que no sigui l’últim
iDimLlista = UBound(oLlista.StringItemList())

if iIndex(0) < iDimLlista then ‘ prepara un Array auxiliar 
Redim sNovaLlista(iDimLlista) ‘ obté els índexos a intercanviar 
i = iIndex(0) 
j = i + 1 ‘ itera per carregar l’array auxiliar 
for k=0 to iDimLlista 
sNovaLlista(k) = oLlista.StringItemList(k) 
next k ‘ intercanvia les posicions en l’array auxiliar 
sAux = sNovaLlista(j) 
sNovaLlista(j) = sNovaLlista(i) 
sNovaLlista(i) = sAux ‘ carrega la llista 
oLlista.StringItemList() = sNovaLlista() ‘ selecciona l’anterior sNovaLlistaSeleccionat(0) = j 
oLlista.SelectedItems = sNovaLlistaSeleccionat 
end if oLlista.Refresh() 
SORTIR: 
End sub

Tanco Spaces. El Bloc continua a Blogger

Després de rumiar-ho, he decidit migrar el Bloc Tecnològic a l’adreça http://apuntstecnologia.blogspot.com de Blogger.

Amb aquest canvi milloro el disseny de la pàgina, la interacció amb
usuaris també és més senzilla i ja no caldrà registrar-se per deixar
comentaris, millora la integració amb xarxes socials, en particular
Facebook i Twitter, tinc a disposició un munt de gadgets nous, i podré
posar el Google Analytics.  En definitiva, hi surto guanyant.

Aprofito també per vincular més estretament el Bloc Tecnològic amb el projecte d’empresa "Serveis Tecnològics i Programari Lliure",
fent que el bloc prengui el seu nom, en comptes del meu particular.
Fins i tot aquest Bloc pot acabar esdevenint la pàgina principal del
projecte d’empresa.

Ara ve la tasca que espero enllestir aviat de migrar els continguts.

Espero que aquest bloc sigui d’utilitat, com ja ho ha estat la seva
primera versió i n’estic segur que ho serà en aquesta nova etapa.

Com automatitzar l’enviament de correus amb OpenOffice.org a Ubuntu Lucid Lynx 10.04 / 09 agost 2010

Com automatitzar l’enviament de correus amb OpenOffice.org a Ubuntu Lucid Lynx 10.04

Inspirat en el codi trobat a
http://trinity.neooffice.org/modules.php?name=Forums&file=viewtopic&t=7330&start=0&postdays=0&postorder=asc&highlight=

L’enviament per correu de l’actual document de treball (menú Fitxer-Envia-Document com a correu electrònic... i altres opcions) amb OpenOffice.org funciona diferent en Windows i Linux. A Windows es basa en les invocacions a la MAPI (Mail API). En canvi a Linux depèn del programa client de correu. Aquesta diferència es tradueix en que en Linux no és possible enviar els correus automàticament sense haver de prémer el botó enviar. De fet, això és una limitació dels programes clients de correu habituals: Thunderbird, Evolution… els que s’especifiquen a a Eines-Opcions-Internet-CorreuElectrònic a Programa de Correu.

Curiosament, el MailMerge no funciona fent servir aquests clients de correu sinó que es basa en una macro en Python que fa un enviament SMTP prenent com a dades de connexió les que es troben a Eines-Opcions-OpenOffice.org Writer-Adreça electrònica de la combinació.

Que a Linux, amb Thunderbird e Evolution calgui prémer el botó enviar és una molt mala notícia de cara a l’automatització d’enviaments.

Tanmateix, encara es pot automatitzar l’enviament. Per a fer-ho caldrà instal·lar des del Centre de Programari de l’Ubuntu l’aplicació de consola sendemail. (si volem enviar fent servir l’SMTP de Google, també caldrà instal·lar libio-socket-ssl-perl i libnet-ssleay-perl)

Aquesta és una aplicació que serveix per a fer exactament el que diu que fa: enviar correus des de la línia de comandes.

Si fem sendemail -h obtenim les opcions:

sendemail-1.56 by Brandon Zehm <caspian@dotconf.net>

Synopsis: sendemail -f ADDRESS [options]

Required:
-f ADDRESS from (sender) email address
* At least one recipient required via -t, -cc, or -bcc
* Message body required via -m, STDIN, or -o message-file=FILE

Common:
-t ADDRESS [ADDR …] to email address(es)
-u SUBJECT message subject
-m MESSAGE message body
-s SERVER[:PORT] smtp mail relay, default is localhost:25

Optional:
-a FILE [FILE …] file attachment(s)
-cc ADDRESS [ADDR …] cc email address(es)
-bcc ADDRESS [ADDR …] bcc email address(es)
-xu USERNAME username for SMTP authentication
-xp PASSWORD password for SMTP authentication

Paranormal:
-b BINDADDR[:PORT] local host bind address
-l LOGFILE log to the specified file
-v verbosity, use multiple times for greater effect
-q be quiet (i.e. no STDOUT output)
-o NAME=VALUE advanced options, for details try: –help misc
-o message-content-type=<auto|text|html>
-o message-file=FILE -o message-format=raw
-o message-header=HEADER -o message-charset=CHARSET
-o reply-to=ADDRESS -o timeout=SECONDS
-o username=USERNAME -o password=PASSWORD
-o tls=<auto|yes|no> -o fqdn=FQDN

Help:
–help the helpful overview you’re reading now
–help addressing explain addressing and related options
–help message explain message body input and related options
–help networking explain -s, -b, etc
–help output explain logging and other output options
–help misc explain -o options, TLS, SMTP auth, and more

És dir, si faig, per exemple

$ sendemail -f elmeucompte@gmail.com -t destinatari@servidor.com -m ‘Enviament de prova’ -s smtp.gmail.com:587 -u ‘Una prova amb sendemail…’ -xu elmeulogin -xp elmeupassword -a /home/albert/Documents/thisdocument.txt -o tls=yes

Enviaré un missatge amb subject “Una prova amb sendemail…”, cos del missatge “Enviament de prova”, al compte de correu “destinatari@servidor.com” des del compte “elmeucompte@gmail.com” adjuntant el document que tinc a l’adreça local /home/albert/Documents/thisdocument.txt fent servir l’SMTP de Gmail amb l’usuari i password de Gmail del meu compte

Doncs bé, sabent tot això, el que puc fer és invocar directament des del OOoBasic a aquesta utilitat, passant la informació que faci falta. Per exemple, amb un codi com aquest:

sub EnviaCorreusShell(sFrom as String, sDestinatari as String, _
sSubject as String, sBody as String, sPathAdjunt as String, _
sHost as String, sLogin as String, sPassword as String, _
sAltres as String)
‘ sendemail -f elmeucompte@gmail.com -t destinatari@servidor.com
‘ -u ‘Una prova amb sendemail…’
‘ -m ‘Enviament de prova’
‘ -a /home/albert/Documents/thisdocument.txt
‘ -s smtp.gmail.com:587
‘ -xu elmeulogin
‘ -xp elmeupassword
‘ -o tls=yes

dim sParametres as string
sParametres = “-f ” & sFrom
sParametres = sParametres & ” -t ” & sDestinatari
sParametres = sParametres & ” -u ” & sSubject
sParametres = sParametres & ” -m ” & sBody
sParametres = sParametres & ” -a ” & sPathAdjunt
sParametres = sParametres & ” -s ” & sHost
sParametres = sParametres & ” -xu ” & sLogin
sParametres = sParametres & ” -xp ” & sPassword
sParametres = sParametres & ” ” & sAltres

‘ Shell(Pathname, Windowstyle, Param, bSync) de la Wiki OooBasic RTL d’OpenOffice

‘ Pathname
‘ the path of the program to be executed.

‘ In MS-Windows, use ConvertToURL(Pathname) otherwise the command will not work
‘ if Pathname contains spaces or national characters.

‘ Windowstyle
‘ the window in which the program is started.
‘ The following values are possible:

‘ * 0 – program receives the focus and is started in a concealed window.
‘ * 1 – program receives the focus and is started in a normal-sized window.
‘ * 2 – program receives the focus and is started in a minimized window.
‘ * 3 – program receives the focus and is started in a maximized window.
‘ * 4 – program is started in a normal-sized window, without receiving the focus.
‘ * 6 – program is started in a minimized window, the focus remains in the current window.
‘ * 10 – program is started in full screen mode.

‘ Param
‘ command line parameters to be transferred to the program to be started.

‘ bSync
‘ wait for shell command to finish flag

‘ * true – wait for shell command to finish
‘ * false – don’t wait for shell command to finish

Shell(“/usr/bin/sendemail”, 6, sParametres, true)

‘ msgbox(“Enviat!”) ‘ ho qualsevol altre avís

end sub

Que invocaria amb una crida com aquesta, per exemple:

EnviaCorreusShell(“elmeucorreu@gmail.com”, “destinatari@ono.com”, _
“prova des de macro”, ” prova d’enviament de correu des de macro”, _
“/home/albert/Documents/thisdocument.txt”, _
“smtp.gmail.com:587”, “elmeulogin”, “elmeupassword”, _
” -o tls=yes”)

La cosa es pot millorar molt i adaptar-la a les necessitats. El següent són exemples diversos de com fer servir SendEmail per a enviar segons diferents criteris. Atenent al que es vulgui fer, adaptarem la invocació al client de correu.

Exemples de Sendemail (de http://www.debianadmin.com/how-to-sendemail-from-the-command-line-using-a-gmail-account-and-others.html)

Email simple

sendEmail -f myaddress@isp.net \
-t myfriend@isp.net \
-s relay.isp.net \
-u “Test email” \
-m “Hi , this is a test email.”

Enviament a molts destinataris

sendEmail -f myaddress@isp.net \
-t “admin <admin@isp.net>” user1@isp.net user2@isp.net \
-s relay.isp.net \
-u “Test email” \
-m “Hi this is a test email.”

Enviament a molts destinataris en còpia i en còpia oculta

(cal fixar-se aquí com, a diferència de l’enviament a molts destinataris amb ‘-t’, amb ‘-cc’ i ‘-bcc’ cal separar els destinataris amb ‘;’)

sendEmail -f myaddress@isp.net \
-t admin@isp.net;user1@isp.net;user2@isp.net \
-cc user2@isp.net tom@isp.net jess@isp.net \
-bcc ra@isp.net dub@isp.net kay@isp.net \
-s relay.isp.net \
-u “Test email with cc and bcc recipients” \
-m “Hi his is a test email.”

Enviament a molts destinataris i amb adjunts

sendEmail -f myaddress@isp.net \
-t admin@isp.net \
-cc user1@isp.net user2@isp.net user3@isp.net \
-s relay.isp.net \
-u “Test email with cc and bcc recipients” \
-m “Hi this is a test email.” \
-a /mnt/storage/document.sxw “/root/My Documents/Work Schedule.kwd”

Enviament de correu amb els continguts del missatge en un fitxer (mètode 1)

cat /tmp/file.txt | sendEmail -f myaddress@isp.net \
-t admin@isp.net \
-s relay.isp.net \
-u “Test email with contents of file”

Enviament de correu amb els continguts del missatge en un fitxer (mètode 2)

sendEmail -f myaddress@isp.net \
-t admin@isp.net \
-s relay.isp.net \
-o message-file=/tmp/file.txt \
-u “Test email with contents of file”

Enviament d’un email HTML: (cal assegurar que l’etiqueta <html> va a l’inici!)

cat /tmp/file.html | sendEmail -f myaddress@isp.net \
-t admin@isp.net \
-s relay.isp.net \
-u “Test email with html content”

obrir, tancar i maximitzar formularis a OpenOffice.org Base / 05 agost 2010

obrir, tancar i maximitzar formularis a OpenOffice.org Base

Una possibilitat a l’hora de realitzar una aplicació d’escriptori amb eines de  programari lliure que involucri una base de dades pot ser ser OpenOffice.org . En particular, OpenOffice.org Base.

Ara bé, quan hom es posa a treballar amb Base, sobretot si abans ha realitzat aplicacions d’escriptori amb Access troba immediatament diferències entre ambdós entorns. I certes coses que són molt fàcils de fer amb Access, són més complicades amb Base o, no es poden fer si es treballa amb el Basic com llenguatge de desenvolupament.

Certament, per no endur-se un disgust, cal tenir ben present que és el que es pot fer i el que no es pot fer amb l’OpenOffice.org.

Algunes de les tasques que podem esperar a l’hora de desenvolupar una aplicació amb OpenOffice.org és que calgui treballar amb formularis.  En general, una aplicació qualsevol consisteix en un conjunt de formularis que interaccionen amb la base de dades, o entre ells i la base de dades. Per exemple, els assistents són una seqüència de formularis que es corresponen amb uns estats i que la transició d’un estat inicial a un estat següent depèn de les decisions que es prenen al formulari corresponent a l’estat inicial.

Tot això es pot fer amb OpenOffice.org. Cal tenir en compte, però, que cada formulari (junt amb el seus subformularis) s’obre com finestra independent. També cal tenir en compte que no podrem ocultar els menús estándards de l’OpenOffice.org. En general, en una aplicació feta sobre OpenOffice.org, serà evident per l’aspecte,pels menús, pel look & feel, que allò és OpenOffice.org.

Doncs bé, en el món Access, obrir, tancar, maximitzar un formulari és una cosa que no costa gaire: hi han macros directes del tipus OpenForm, o des del VBA d’Access és tan senzill com indicar el nom del formulari i invocar els mètodes Show,o Close, o Maximize. No té truc.

En canvi, a OpenOffice.org, i això sobta molt, no és tan directe obrir formularis des de l’OOo Basic. I tancar-los o maximitzar-los és realitza amb una invocació més semblant a com ho fa Access, però que, tanmateix, és sorprenent.

Per obrir un formulari, ens caldrà una snippet com el següent:

Sub ObrirForm(sNomForm as String, sBaseDades as String)
    ‘ variables
    ‘ necessari una array de propietats de dimensió 2 elements per invocar a loadComponentFromURL
    Dim prProp(1) as New com.sun.star.beans.PropertyValue
    ‘ objectes per a accedir a compartir la connexió
    Dim oDatabaseContext, oDataSource, oForms, oConnection
   
    ‘ obté el context de base de dades
    oDatabaseContext = createUnoService(“com.sun.star.sdb.DatabaseContext”)

    ‘ obté  el datasource corresponent a la base se dades
    oDataSource = oDatabaseContext.getByName(sBaseDades)

    ‘ obté la col·lecció de formularis de la base de dades
    oForms = oDataSource.DataBaseDocument.getFormDocuments

    ‘obté la connexió
    oConnection=ThisComponent.Parent.DataSource.getConnection(“”,””)

    ‘ li indica que la connexió és la de la base de dades
    prProp(0).Name = “ActiveConnection”
    prProp(0).Value = oConnection
   
    ‘ li indica que cal obrir el formulari
    prProp(1).Name = “OpenMode”
    prProp(1).Value = “open”

    ‘  obre el formulari de nom sNomForm,passant-li connexió activa
    oForms.loadComponentFromURL(sNomForm, “”,0,prProp())
end sub

Per tancar el formulari, en canvi, es pot fer així: posem un botó de “tancar formulari”, a les propietats del control, en la pestanya general, en la propietat “Acció”, trio: “obre el document o la pàgina”; i a la propietat URL “.uno:CloseDoc”. no és broma.

I per posar el formulari a pantalla completa? (compte! posar a pantalla completa no és el mateix que maximitzar)
es pot fer associant el següent codi a l’event “en carregar” del formulari

Sub PantallaComplerta(Event As Object)
   Dim oFrame As Object
   Dim oDispatchHelper
   oFrame=Event.Source.Parent.Parent.CurrentController.Frame
   oDispatchHelper=CreateUnoService("com.sun.star.frame.DispatchHelper")
   oDispatchHelper.ExecuteDispatch(oFrame,".uno:FullScreen","",0,Array())
End Sub

I maximitzar? directament no es pot. És degut a que la maximització d’una finestra és una tasca que realitza el gestor de finestres subjacent… i de gestors de finestres en poden haver de diferents a Linux. L’enfocament és diferent. El que es busca és redimensionar i recol·locar la finestra per a fer que ocupi tota la pantalla. Realment no està maximitzat. De moment no poso el codi perquè els que he trobat i estic provant no em convencen.

El que sí que es pot fer, en to cas, és maximitzar el formulari  en mode de disseny eliminant tots els elements, barres d’eines, d’estat… que no vulgui que apareguin en la visualització en mode formulari, i desar. En principi, en obrir el formulari de nou aquest s’obrirà maximitzat i així es mantindrà mentre l’usuari no el desmaximitizi. No és la millor solució, però…

En Windows sí que es diposa d’un snippet per a maximitzar.

Declare Function GetActiveWindow Lib “user32” Alias “GetActiveWindow” () As Long
Declare Function ShowWindow Lib “user32” (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long

Public Sub GlobMaxWindow()

Dim WinWnd As Long, TytOkna As String
    TytOkna=ThisComponent.CurrentController.Frame.Title
    WinWnd = GetActiveWindow ‘get active window handle
    ‘WinWnd = FindWindow(“”, TytOkna)’ Different function get window handle by Title window

    If WinWnd = 0 Then Exit Sub

    ‘Show window

    ShowWindow WinWnd, 3 ‘0-hide, 1-to yor seting size, 2-minimalize, 3-max size
End Sub

Formulari Mestre-Detall amb OpenOffice.org / 02 agost 2010

Formulari Mestre-Detall amb OpenOffice.org

La construcció d’un formulari “mestre-detall”, per a presentació o per a introducció d’informació és senzilla de realitzar fent us de
“subformularis” dintre de “formularis”.

En un post anterior havia distingit entre diàlegs i formularis. Un diàleg és una interfase gràfica realitzada amb l’editor de diàlegs. un formulari és una interfase gràfica realitzada sobre el document. En el cas de l’OpenOffice.org Base, el formulari és un objecte del tipus Writer però vinculat amb la base de dades.

Això és intressant: quan generarem un formulari amb l’assistent, ens demanarà que el desem. Fixem-nos que el formulari es desa com un .odt (writer). diferent de l’.odb (base). Desem, a continuació, la base de dades.

Ara bé, si examinem el fitxer de la base de  dades .odb (que no és més que un fitxer .zip)  i el comparem amb el fitxer .odt (un altre fitxer  zip) del writer del formulari que veiem? doncs que a l’odb hi ha una carpeta forms dins la qual es troba la mateixa estructura del document writer del form.

Per a Base els formularis es desen conjuntament amb l’odb que conté la definició de la base de dades.

Un cop aclarat això, vaig a fer el mestre detall.

Es diposa d’un assistent per a realitzar formularis del tipus mestre-detall amb l’OpenOffice Base. Aquest assistent ens dona les claus per a realitzar el mateix formulari mestre-detall manualment, o per a realitzar un mestre-detall amb les altres aplicacions (Writer, Calc, Draw o Impress)

És important comprendre que el subformulari és un objecte lògic més que no pas visible. El “navegador de formularis” ens pot ajudar a copsar la idea.

Faré un exemple amb l’assistent, i analitzaré el que s’ha obtingut per tal d’aprendre’n les claus.

El primer de tot és crear una base de dades amb dues taules, una serà la taula mestra i l’altre, la de detall.
Taula1: id (PK, Primary Key, numèric, autoincrement) i valor (text). Serà la taula mestra.
Taula2: id (PK, Primary Key, numèric, autoincrement), idfk (FK, Foreign Key, columna de rel·lació a la taula1), valor, traducció. Aquesta serà la taula de detall.

Informo les dues taules amb dades:




Un cop creades les dues taules, executo l’assistent de creació de formularis: click a “Crear un formulari utilitzant l’auxiliar…”

1. Selecciono les columnes de la taula mestra: taula1 i click a següent

2. Afegeix el formulari. Depenent de les bases de dades sobre les que treballem, podrem triar una relació existent, o bé haurem de sel·leccionar manualment els camps de rel·lació. Click a següent.

3. Indico els camps dels sub-formulari que apareixeran. En aquest exemple, els trio tots. Click a següent.

4. Ara trio els camps de rel·lació entre el formulari mestre (la taula1) i el sub-formulari de detall (la taula2)
Indico que la columna IDFK de Taula2 és FK a ID de Taula1. Click a següent.

5. Trio un disseny de presentació. Click a següent.

6. Li indico quina funcionalitat tindrà el formulari (només lectura, o permetrà afegir, esborrar, modificar…). Click a següent.

7. Finalment trio estil de presentació: colors, controls 3D…  Clik a següent.

8. I li dono nom al formulari: “prova-mestre-detall” i click a “Fi.”

Ara puc provar  el formulari. Depenent del tipus de presentació que hagi triat en el pas 5 serà més evident el funcionament. Vist el cost de crear formularis amb l’assistent,  és una bona idea  provar els diferents formats de presentació.

En resum, podem afegir nova informació, esborrar-la..canviar-la. Tot s’aconsegueix automàticament sense haver de programar. No està gens malament.

Si passo al mode de disseny podré veure com funciona. Tanco i deso el formulari. I l’obro per edició

Obro el navegador de formularis

I examinem el navegador de forms

Puc veure que hi han dos formularis: el MainForm que conté dues labels, un camp amb format per a l’ID, un camp de text, i un subformulari SubForm.

En podria crear un altre. Si faig click a MainForm amb el botó de la dreta del mouse puc fer Nou Formulari que serà, en realitat, un nou subformulari. Si faig click amb el botó de la dreta sobre el títol Formularis, en canvi, el que creo és un nou formulari que serà independent. Puc aniuar formularis dins formularis a molts nivells.

El Navegador de formularis és, doncs, una potent eina de disseny. Remarco també que l’estructura de forms i subforms que es manifesta i dissenya en el navegador no té, en canvi, una representació visual. Un form pot ser, doncs, molt complex lògicament, malgrat que potser la seva interfase gràfica no ho sigui gaire.

Però anem poc a poc, si vaig fent click amb el botó de la dreta del mouse als diferents elements que apareixen al navegador de formularis, en puc examinar les propietats.

Així, puc veure com els camps de text estan associats a columnes de les taules de la base de dades, i com es permet o no, l’edició, la creació o l’eliminació de la informació associada.

El més interessant és examinar els formularis. Examino el formulari mestre (MainForm)

i com es vincula el subformulari de detall (SubForm) amb el formulari mestre:

La creació de formularis mestre detall és redueix a crear amb el navegador de formularis

1. primer de tot, tenir unes taules de mestre i detall rel·lacionades.
2. Un formulari mestre
3. Un formulari de detall
4. Vincular cada formulari a la taula corresponent
5. definir les relacions entre els formularis a les propietats de dades del subformulari
6. afegir els camps rel·lacionats amb columnes fent servir la llista de sel·lecció de camps

o bé afegir un control (camp de text, camp formatat, check box, radio button…)  i vincular-lo a través de la seva pàgina de propietats a una columna d’una taula.

El Control Taula (en la paleta de “més controls”) en el formulari mestre ens mostra el contingut de la taula, Però si s’ubica en el subformulari es vincula automàticament i ens permet visualitzar d’un sol cop totes les files relacionades en la taula de detall.

Els camps de ListBox i de ComboBox en el formulari de detall, en canvi, no estan preparats par a la vinculació mestre-detall. Es poden carregar amb el contingut d’una taula,o una llista de valors, o el resultats d’una consulta.

Una comparativa entre algunes bases de dades a Ubuntu / 31 juliol 2010

Una comparativa entre algunes bases de dades a Ubuntu

Des del punt de vista del desenvolupador. Entorn Ubuntu Lucid Lynx 10.04.

He considerat les següents bases de dades:

Bases de dades d’aplicació:
OpenOffice.org Base – HyperSonic DB (OpenOffice.org 3.2)
SQLite: el motor SQLite passa per ser el més eficient de tots per a bases de dades d’aplicació. Se’l compara amb el motor JET de l’Access. És la base de dades que s’amaga darrera de Kexi, l’aplicació de gestió de bases de dades de la suite KOffice de KDE.
dBase: el vell format .DBF dBase.

Servidors:
MySQL: El Servidor SQL que primer et ve al cap.
FireBird: La versió OpenSource de InterBase de Borland. Versions de servidor, d’aplicació i embedded. Molt escalable.
PostgreSQL: El més antic dels servidors SQL OpenSource. GLOM, una eina de desenvolupament senzill d’aplicacions de bases de dades, està basat en PostgreSQL.

I també he considerat les següents eines de desenvolupament:

OpenOffice.org Basic (OOoBasic)
Gambas2
Lazarus
PHP
java

Per què aquestes eines de desenvolupament i aquestes bases de dades? docs perquè, a priori, em semblen les que em donaran una major productivitat a l’hora de desenvolupar aplicacions.
En el concepte de major productivitat incloc la facilitat d’instal·lació, disponibilitat d’eines gràfiques de configuració, disponibilitat d’entorns de desenvolupament…

Això fa que, per exemple, no hagi considerat Python o C/C++ al no disposar d’entorns RAD (Rapid Application Development) lliures per a aquests llenguatges. Gambas2, Lazarus i OOoBasic, en canvi, sí que en disposen.

Cal dir que la combinació Python o C++ amb Glade no és exactament un RAD, però, tanmateix, se li assembla prou. De fet, és tracta de la tria natural, obvia, per als programadors de l’entorn Gnome. Farem experiments. (Nota afegida 12/08/2010)

PHP i Java els he considerat per que són els dos llenguatges de servidor per a desenvolupar aplicacions web. Per a Java i per a PHP es disposa d’IDEs prou bons i complets (i pesats), com Eclipse o NetBeans.

El resum de la situació és el següent:

PostgresSQL  (Versió 8.4)
Accessible sense problemes amb Gambas2,  OpenOffice.org , Lazarus, PHP i Java

Firebird
Accessible sense problemes amb Gambas2, Lazarus i PHP (no he provat l’accés amb java)
no funciona driver JDBC de FireBird amb OpenOffice
no funciona driver ODBC de EasySoft amb OpenOffice
no funciona driver ODBC de FireBird amb OpenOffice
Conclusió: no disponible fàcilment sobre OpenOffice

SQLite2
Accessible sense problemes amb OpenOffice (driver ODBC),  Gambas2, Lazarus (però no és pot tenir simultàniament els controls de SQLite 2 i SQLite3),  PHP (no he provat l’accés amb java)

SQLite3
Accessible sense problemes amb OpenOffice (driver ODBC),  Gambas2, Lazarus (però no és pot tenir simultàniament els controls de SQLite 2 i SQLite3) .
Problemes per instal·lat PHP5-Sqlite3 amb Lucid Lynx. Sembla que es pot fer funcionar, amb versions anteriors ho feia! però per alguna rao, a la Lucid Lynx no es disposa del paquet (per què?). No he provat d’accedir-hi amb Java.

OpenOffice.org Base
Es tracta d’una HyperSOnic DB i, per tant, és accessible per aplicacions java amb JDBC.
No s’hi pot accedir (de forma útil) des  de Gambas2, Lazarus ni PHP. Realment a OpenOfficer.org Base només s’hi pot accedir bé amb… OpenOffice.org. Base.
Ara bé, en el món java, la HyperSonic és una molt bona tria (òptima) quan cal una base de dades d’aplicació.

dBase3
Sense problemes d’accés amb Gambas2, Lazarus, OpenOffice (nadiu) i Java. No funciona amb PHP però podria funcionar. En la Ubuntu Lucid Lynx aquest suport, per alguna raó, no està disponible (cal pensar que s’hi pot afegir)

MySQL
Sense problemes d’accés amb Gambas2, OpenOffice, PHP i Java.  Lazarus només suporta correctament fins 5.0. Però a la Lucid Lynx la versió del repositori és la 5.1!

Tinc, doncs, algun criteri addicional a l’hora de fer estimacions d’esforç al planificar desenvolupaments amb aquestes eines lliures.