sabato 10 ottobre 2009

Conta cellule

Un utente del Newsgroup it-alt.comp.software.openoffice ha postato una domanda interessante (dal mio punto di vista ovviamente).

Ma vediamo in dettaglio cosa dice l'amico Torakiki78:

Sto cercando di fare un file con openoffice calc che mi serve per
contare delle cellule... ecco come dovrebbe essere:
la conta è di 100 cellule in tutto e di ciascuna devo segnalare se
è mobile, poco mobile o immobile. Premendo 1, la cellula è mobile.
Premendo 2 la cellula è poco mobile. Premendo 3 la cellula è
immobile.

Ho fatto un file (che se volete posto...) con openoffice calc in
cui segno per ogni cella (dalla A4 alla A104) premendo 1,2 oppure 3 e
poi invio per passare alla cella successiva (cioè quella sotto).

Le mie richieste sono:
Vorrei poter premere 1, 2 o 3 e SENZA dover premere invio poter
passare alla cella sotto. In più vorrei che quando arrivo alla
cella A54 poter sentire un suono che mi avvisa che sono arrivato a
contare 50 cellule.
Vorrei anche che, se premo 4 o 5 o 9 (o comunque un numero diverso
da 1,2,3), che non venisse segnalato....
Non so usare le macro, e un pochino le funzioni....

Mi potete aiutare?

E come no! Siamo qui per questo :-)

Dunque, prima di procedere però, cito la risposta di Roberto Montaruli:

Il tuo e' un problema di interfaccia, non di applicazione.
Tu vuoi una interfaccia utente su misura.
Richiesta rispettabilissima.
Ma Calc non e' una applicazione di interfaccia, e' un gestore di
foglio elettronico.
Gestisce i dati, non l'input degli stessi.

In effetti la risposta di Roberto è molto sensata, probabilmente con un piccolo programma standalone si potrebbe raccogliere l'input per poi salvarlo ad esempio in un file CSV.

In ogni caso, OpenOffice.org dispone di tutti i mezzi per costruire la piccola interfaccia di cui abbiamo bisogno in modo abbastanza pulito.

Per cominciare ci serve almeno una rudimentale specifica:

Specifica di progetto

L'idea a grandi linee è la seguente:

una finestra di dialogo modale con un campo di testo che riceverà l'input

ogni volta che l'utente premerà un tasto, se il tasto corrisponde a 1 o 2 o 3 il valore verrà “appeso” ad un vettore, diversamente il valore verrà rigettato

Una variabile numerica terrà il conto di quanti inserimenti sono stati fatti, il valore attuale verrà mostrato nel dialogo mediante un controllo “testo fisso”

Al cinquantesimo inserimento verrà emesso un beep mentre al centesimo, doppio beep e uscita dal dialogo.

All'uscita provvederemo a creare un nuovo documento Calc e a trasferire i valori conservati nel vettore.

Naturalmente tutto il progetto sarà impacchettato come extension. Nell extension verrà inserita anche una piccola barra degli strumenti con un solo pulsante che servirà per lanciare il dialogo.

Preparazione ambiente

Per prima cosa occorre creare una nuova libreria macro condivisa che chiameremo “ContaCellule”














Design del dialogo

Ora passiamo a disegnare il dialogo come segue:


Il dialogo si chiamerà DlgContaCellule

Il controllo in alto è un fixed text che ho chiamato lblCount, mentre quello sottostante è un text edit che ho chiamato txtInput






Per essere sicuri che all'apertura del dialogo il focus (e quindi l'input dell'utente) sia immediatamente dirottato su txtInput occorre impostare la proprietà sequenza = 0

Come ulteriore precauzione, tutti i rimanenti controlli avranno la proprietà Tabstop = No

Questo impedirà loro di ricevere il focus quando si preme il tasto tabulazione.

Altri accorgimenti:

Pulsante OK : impostare la proprietà Abilitato = No e la proprietà Tipo di pulsante = OK

Pulsante Annulla : impostare la proprietà Tipo di pulsante = Annulla


Eventi

Ora dobbiamo creare la procedura che verrà usata per intercettare l'input dell'utente.

Sub txtInput_KeyPressed(oEvt)

End Sub

Questa procedura dovrà essere collegata all'evento Tasto premuto del controllo txtInput
















Mostrare il dialogo

Ora aggiungiamo il codice per mostrare il dialogo:

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

Private oDlg As Object

'_____________________________________________________________________________
Sub ShowDialog
DialogLibraries.loadLibrary("ContaCellule")
oDlg = CreateUnoDialog(DialogLibraries.ContaCellule.DlgContaCellule)

'initialize controls
oDlg.Model.txtInput.Text = ""
oDlg.Model.lblCount.Label = ""

IDlgResult = oDlg.execute()

If iDlgResult = 1 Then
'user pressed OK
'
'
'
'
End If

End Sub

Ovviamente il codice è ancora incompleto.

Manca infatti la gestione dell'evento key pressed ed inoltre occorre conservare i dati inseriti per poi riversarli opportunamente in un documento Calc

Codice completo

Ecco il codice completo:

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

Private oDlg As Object
Private iCount As Integer
Private mValues()


'_____________________________________________________________________________
Sub ShowDialog
DialogLibraries.loadLibrary("ContaCellule")
oDlg = CreateUnoDialog(DialogLibraries.ContaCellule.DlgContaCellule)

'initialize controls
oDlg.Model.txtInput.Text = ""
oDlg.Model.lblCount.Label = ""

IDlgResult = oDlg.execute()

If iDlgResult = 1 Then
'user pressed OK

'create a new Calc doc
sUrl = "private:factory/scalc"
oDoc = StarDesktop.LoadComponentFromURL(sUrl,"_default",0, Array())
oSheet = oDoc.Sheets(0)

'put the data in the column A starting from row 4
For I = LBound(mValues()) To UBound(mValues())
iRow = I + 3
oCell = oSheet.getCellByPosition(0, iRow)
oCell.FormulaLocal = mValues(I)
Next I
End If

End Sub


'_____________________________________________________________________________
Sub txtInput_KeyPressed(oEvt)
Dim sChar As String

sChar = oEvt.KeyChar
If (sChar = "1") Or (sChar = "2") Or (sChar = "3") Then
If iCount < 100 Then
'store the data
AppendItem(mValues(), sChar)

'update the control content
Select Case sChar
Case "1" : oEvt.Source.Text = "Mobile"
Case "2" : oEvt.Source.Text = "Poco mobile"
Case "3" : oEvt.Source.Text = "Immobile"
End Select

'beep when 50th data has been inserted
If iCount = 49 Then
Beep
End If

iCount = iCount + 1
oDlg.Model.lblCount.Label = iCount

Else
oEvt.Source.Text = "Fine!!"
'enable the OK button and alert the user that the end is reached
oDlg.Model.cmdOk.Enabled = True

Beep
Wait 200
Beep
Wait 200
Beep

End If
Else
'invalid input
oEvt.Source.Text = "-N/A-"

End If

End Sub

'_____________________________________________________________________________
Sub AppendItem(mList(), vItem)
Dim iMax As Long

iMax = UBound(mList())
iMax = iMax + 1
Redim Preserve mList(iMax)
mList(iMax) = vItem

End Sub

Impacchettamento e distribuzione

Non rimane altro che confezionare la nostra mini applicazione.

Usando l'extension BasicAddonBuilder , in pochi passaggi è possibile esportare la libreria appena creata come extension:


Passaggio 1: Selezione libreria











Passaggio 2: Opzioni generali











Passaggio 3: Definizione della barra degli strumenti

Aggiungendo un nuovo pulsante nella barra, nel dialogo delle proprietà sarà possibile definire il comando assegnato (che nel nostro caso sarà la macro ShowDialog ) e altre caratteristiche come ad esempio l'icona, o il contesto che indica semplicemente in quali componenti di OpenOffice.org sarà visibile il nuovo pulsante.













Passaggi conclusivi

Nei passaggi successivi è possibile indicare ulteriori caratteristiche come ad esempio la licenza, il numero di versione, un testo descrittivo. Ecc.

In ultimo verrà chiesto di indicare un percorso per salvare la nuova extension nel proprio disco fisso.

L'extension così creata sarà installabile in qualsiasi PC ove sia presente OpenOffice.org

Per i più pigri, l'extension già assemblata è disponibile qui:

http://www.paolo-mantovani.org/downloads/ContaCellule/

A presto!