Tips&Tricks I trucchi del mestiere

 

Ottimizzare l’utilizzo dei combobox


Capita spesso di utilizzare maschere di inserimento/variazione dati in cui si devono selezionare dei valori provenienti da alcune tabelle in condizioni di carenza di spazio sulle form. Per ovviare a questo problema esistono i ComboBox, ed il componente data-aware dbComboBox.
Le selezioni da ComboBox precaricati con i valori contenuti in una tabella non presentano difficoltà se la riga di testo della selezione è costituita da un solo campo che è poi anche una chiave (o un indice univoco) per la tabella sorgente dei dati. Occorre scrivere un po’ di codice se invece la riga di testo visualizzata dal ComboBox deve contenere i dati di due o più campi, e se, in base ad un altro valore presente nella tabella, si desidera cambiare il colore del testo di visualizzazione.
Tip fornito dal sig. P.Peri

L’idea semplice che sta dietro a questa soluzione è quella di utilizzare un carattere non stampabile che separi i campi all’interno della stringa di testo che viene utilizzata come riga del ComboBox. - ho scelto di utilizzare il carattere CR (#13) – e rendere visibili solo i campi desiderati, mentre quelli necessari alla ricerca univoca nella tabella vengono nascosti. In fase di cambiamento dell’indice attivo del ComboBox occorre procedere all’operazione inversa, ovvero ricostruire i campi necessari alla ricerca univoca.
Per esempio (esempio che non ha nessuna attinenza con le applicazioni reali) ho costruito una tabella Access la cui struttura è la seguente:

Tabella_Persone
ID			Contatore		Chiave primaria
Cognome		Testo (20)		Indicizzato (duplicati ammessi)
Nome			Testo (20)		Indicizzato (duplicati ammessi)
Data_di_nascita	Data/Ora
Luogo_di_nascita	Testo (40)
Codice_fiscale	Testo (16)		Indicizzato (duplicati non ammessi)
Attivo			Sì/No

Il campo privilegiato per la ricerca è ID, ma la selezione da parte dell’utente avviene in base ai campi Cognome e Nome che saranno i soli visualizzati nel ComboBox. Il campo Attivo determinerà invece se il colore con cui vengono scritti i nomi nel ComboBox è nero (o un qualunque altro colore di default) oppure rosso (o un qualunque altro colore di evidenziazione).
Per poter scrivere nell’oggetto canvas del controllo ComboBox occorre poter “bypassare” il drawing di default dello stesso, cosa che si ottiene impostando la proprietà Style a csOwnerDrawFixed. Infine per poter eseguire la selezione in ordine alfabetico sul controllo occorre impostare la proprietà Sorted a True.
Il codice è presente in UnitComboBoxPluricolonna.pas ed è presente, insieme ad un’applicazione di esempio, nel cd-rom allegato alla rivista e/o sul sito web di ioProgrammo (www.ioprogrammo.it)



Copiare i dati tra due database


Il programma è utile per copiare i dati di una tabella da un DB all’altro passando i driver dei DB come parametri alla JVM; il tip è strutturato per esemplificare il trasferimento di una singola tabella "Utenti" i cui campi sono Nome,Cognome,cod.
Il codice è presente in formato sorgente nel cd-rom allegato alla rivista e/o sul sito web di ioProgrammo (www.ioprogrammo.it)
Tip fornito dal sig. R.Gabbarelli

import java.sql.*;
public class SQLServerToAccess {
	static final String FORNAME="sun.jdbc.odbc.JdbcOdbcDriver";
	static String DriverInput;
	static String DriverOutput;
	
	public static void main(String[] args) throws ClassNotFoundException{
		try{
			Class.forName(FORNAME);
			DriverInput="jdbc:odbc:"+args[0];	//driver del database sql
			DriverOutput="jdbc:odbc:"+args[1];	//driver del database access
			
			Connection conIn=DriverManager.getConnection(DriverInput);
			Connection conOut=DriverManager.getConnection(DriverOutput);
						
			Statement 
stIn=conIn.createStatement(ResultSet.TYPE_SCROLL_INSE
NSITIVE,ResultSet.CONCUR_READ_ONLY);
			ResultSet rs=stIn.executeQuery("select * from Utenti");//il resultset 
dev'essere scrollabile a causa di un problema
			
			rs.first();
			do{
				String nomeUtente=rs.getString(1);
				String cognomeUtente=rs.getString(2);
				int codiceUtente=rs.getInt(3);
				
				Statement stOut=conOut.createStatement();
				stOut.execute("INSERT INTO Utenti 
VALUES('"+nomeUtente+"','"+cognomeUtente+"',"+
codiceUtente+")");
			}
			while(rs.next());
			
			rs.last();	//questa e le righe a seguire servono ad ovviare ad un 
problema di inserimento dell'ultimo valore
			Statement first=conOut.createStatement();	//inserito nel DB di 
partenza
			first.execute("insert into Utenti 
values('"+rs.getString(1)+"','"+rs.getString(2)+"',"+rs.getI
nt(3)+")");
			
			System.out.println("Copia Terminata!");
			System.exit(0);
			}catch(SQLException e){
			System.out.println("SQL Exception!");
			System.exit(1);
		}
	}
}



Eseguire operazioni in background


Una serie di classi Java per eseguire una serie di operazioni in background. Basta estendere AbstractJob implementando execute() e BackgroundJobExecutor esegiura` in serie i lavori che vengono inseriti.
Le classi sono: Prova.java, AbstractJob.java e BackgroundJobExecutor.java.
I codici sono presenti in formato sorgente nel cd-rom allegato alla rivista e/o sul sito web di ioProgrammo (www.ioprogrammo.it)
Tip fornito dal sig. M.Schiavon

import java.util.*;

public class BackgroundJobExecutor implements Runnable {
	private Queue queue;
	private boolean stopRequest = false;
	private boolean stopping = false;
	private Thread thread;
	private final AbstractJob nop = new AbstractJob() {
		public void execute() {
			dispose();
		}
	};
	public BackgroundJobExecutor() {
		queue = new Queue();
		thread = new Thread(this);
	}
	/**
	 * Inizia a processare i job
	 */
	public void start() {
		thread.start();
	}
	/**
	 * Aggiunge un job alla coda
	 */
	public boolean add(AbstractJob job) {
		if (job == null) {
			throw new NullPointerException("Job cannot be null");
		}
		if (stopRequest || stopping) {
			throw new IllegalArgumentException("BackgroundJobExecutor has been 
stopped.");
		}
		return queue.put(job);
	}
	public void run() {
		while (!stopRequest) {
			AbstractJob l = (AbstractJob)queue.get();
			if (l == null) {
				break;
			}
			l.execute();
		}
		dispose();
	}
	/**
	 * Termina i job in coda e si ferma
	 */
	public void stop() {
		if (stopRequest) {
			throw new IllegalArgumentException("BackgroundJobExecutor has been 
stopped.");
		}
		if (!stopping) {
			stopping = true;
			queue.putLast(nop);
		}
	}
	/**
	 * Ferma l'esecusione senza necessariamente aver terminati i job in coda
	 */
	public void dispose() {
		stopRequest = true;
		queue.clear();
		if (thread != null) {
			thread.interrupt();
			thread = null;
		}
	}
	private class Queue {
		private List list = new LinkedList();
		public synchronized Object get() {
			while (list.size() == 0) {
				try {
					wait();
				} catch (InterruptedException ex) {
					return null;
				}
			}
			Object o = list.iterator().next();
			list.remove(o);
			return o;
		}
		public synchronized boolean put(Object obj) {
			boolean b = list.add(obj);
			notify();
			return b;
		}
		public synchronized void clear() {
			list.clear();
		}
		public synchronized void putLast(Object o) {
			list.add(list.size(), o);
		}
	}
}



Una classe che implementa il controllo e/o la creazione del codice fiscale


Vista la prolissità del codice, presentiamo solo un’applicazione che sfrutta la classe per creare il codice fiscale; il sorgente della classe è presente nel cd-rom allegato alla rivista e/o sul sito web di ioProgrammo (www.ioprogrammo.it)
Tip fornito dal sig. R.Sensale

<!doctype html public "-//W3C//DTD HTML 4.0 //EN">
<html>
<head> Title here! </head> <body> <?php $cognome='Sensale'; $nome='Rosario'; $sesso='M'; $DataNascita="19/05/1980"; $Comune="Napoli"; //CF($cognome,$nome,$sesso,$DataNascita,$Comune); include_once 'CF.class'; $object = new Class_CF(); $object->SetLastName('Sensale'); $object->SetName('Rosario'); $object->SetBornDate('19/05/1950'); $object->SetSex('m'); $object->SetCom('Napoli'); echo $object->Create_CF(); echo $object->Check_CF('XXXOKPKOMAKAK'); ?> </body> </html>


Utilizzo dei template


Per utilizzare i template PHP al meglio proviamo a seguire i seguenti semplici passi: la prima operazione da fare è scomporre la pagina nei suoi elementi fondamentali, ad esempio

- body
- colonna sx
- colonna centrale

E trovare in questi elementi i sotto-elementi ripetitivi ad esempio:

- voce di menu
- sommario di un articolo.

Per ognuno di questi sostituite il contenuto dinamico dell'elemento con una variabile. Ad esempio il codice dell'elemento 'voce di menu' potrebbe passare da:


	        <a href="menu.htm">menu</a>
a: <a href="$collegamento">$voce</a>

Se l'elemento è per esempio la colonna sinistra del vostro sito potete scomporla in molti sotto elementi, che poi saranno riassemblati con un metodo intuitivamente simile a quello delle matrioske.
Fatto questo salvate gli elementi fondamentali e quelli ripetitivi in un record di una tabella di un database. e associate ad ogni elemento un id univoco. A questo punto nella vostra pagina php si tratta soltanto di richiamare gli elementi memorizzati richiesti dalla pagina e riempire le loro variabili con i valori voluti.
Ad esempio supponiamo che l'elemento 'colonna sinistra' contenga:


	<p>$menu</p>

Potremmo recuperare l'elemento 'voce di menu' dal database ed effettuare un procedimento simile al seguente:


	<?
        $collegamento = "home.htm";
        $voce = "Torna all'homepage";
        eval("\$menu .= \"".$vocedimenu."\";");        \\ dove $vocedimenu contiene l'elemento dell'esempio precedente.
        $collegamento = "links.htm";
        $voce = "Visita i link";
        eval("\$menu .= \"".$vocedimenu."\";");        
        eval("\$outputfinale .= \"".$colonnasinistra."\";");   \\ 
		$colonnasinistra contiene il template della
?>

La potenza che si ottiene lavorando con i template è altissima. Tra i vantaggi si può elencare la flessibilità, la riusabilità del codice e la chiarezza del sorgente generato.
Tip fornito dal sig. S.Paganotti



Una rappresentazione grafica per i nostri dati


Alcune applicazioni necessitano, dopo aver elaborato un certo numero e tipo di dati, di mostrare i risultati ottenuti con l'ausilio di controlli ad alto impatto visivo come i grafici. Esistono numerosi controlli di terze parti che offrono la possibilità di risolvere questo problema, ma con le possibilità che il Framework .NET ci offre, è possibile creare questi controlli personalmente.
La procedura allegata, sviluppata in Visual Basic .NET permette la creazione di un controllo per la creazione di semplici grafici, con la possibilità di inserire etichette per ogni punto del grafico, scelta dei colori delle linee, zoom in/out, etc...
Il codice, data la sua prolissità, è presente nel cd-rom allegato alla rivista e/o sul sito web di ioProgrammo (www.ioprogrammo.it)
Tip fornito dal sig. P.Libro



Come inviare un FAX dal proprio PC


Il codice permette di implementare in una propria applicazione l’invio di documenti es. Word, PDF, Excel (..tutti i documenti stampabili) via fax usando i Fax Services nativi di Windows 2000.
Per funzionare ovviamente occorre che sul PC/Server sia installato Microsoft Fax (viene installato automaticamente quando si installa un modem sul sistema) e che dunque esista la stampante Fax e nessun altro software aggiuntivo o a pagamento. Nell’esempio e’ compreso anche un banale form che permette di specificare il numero del destinatario, il nome del file documento da allegare (*.doc,*.pdf) e l’eventuale cover da allegare.
Tale cover page deve essere realizzata con l’apposito cover designer fornito da Microsoft (Start->Impostazioni->Pannello di controllo->Fax->folder “Frontespizi” ->Nuovo).
Il codice è presente in formato sorgente nel cd-rom allegato alla rivista e/o sul sito web di ioProgrammo (www.ioprogrammo.it)(www.ioprogrammo.it)
Tip fornito dal sig. S.Aleotti

Option Explicit

Private Const OF_EXIST = &H4000

Private Const OFS_MAXPATHNAME = 128
Private Const ERROR_FILE_NOT_FOUND = 2&
Private Const HFILE_ERROR = (-1)

Private Declare Function GetComputerName Lib "kernel32" Alias "GetComputerNameA" (ByVal lpBuffer As String, nSize As Long) As Long
Private Declare Function OpenFile Lib "kernel32" (ByVal lpFileName As String, lpReOpenBuff As OFSTRUCT, ByVal wStyle As Long) As Long
Private Type OFSTRUCT
        cBytes As Byte
        fFixedDisk As Byte
        nErrCode As Integer
        Reserved1 As Integer
        Reserved2 As Integer
        szPathName(OFS_MAXPATHNAME) As Byte
End Type

Public Function FileExists(Path As String) As Boolean
Dim o As OFSTRUCT
Dim i As Integer

o.cBytes = Len(o)

i = OpenFile(Path, o, OF_EXIST)

If (i > HFILE_ERROR) Then
    FileExists = True
Else
    FileExists = (Err.LastDllError <> ERROR_FILE_NOT_FOUND)
End If
Err.Clear
End Function
Public Sub DisabilitaControlli(value As Boolean)
Dim c As Control
    Frame1.Enabled = value
    For Each c In FormMain.Controls
    
    On Error Resume Next
    If (c.Container.Name = Frame1.Name) Then c.Enabled = value
    Err.Clear
    Next
End Sub
Function ComputerName() As String
    Dim buffer As String * 512, length As Long
    length = Len(buffer)
    If GetComputerName(buffer, length) Then
        ComputerName = Left$(buffer, length)
    End If
End Function

Private Sub CHK_COVER_Click()
Dim i As Integer
Dim c As Control

If (CHK_COVER.value = 1) Then
    DisabilitaControlli True
Else
    DisabilitaControlli False
End If
End Sub

Private Sub Command1_Click()

    Dim objFaxServer As Object
    Dim objFaxDoc As Object
    On Error GoTo ErrTrap

    If (RTrim(TXT_SERVER.Text) <= "") Then
        MsgBox "Specificare il server", vbCritical Or vbOKOnly, Caption
        TXT_SERVER.SetFocus
        Exit Sub
    End If
    If (RTrim(TXT_FILE.Text) <= "" Or Not FileExists(TXT_FILE.Text)) Then
        MsgBox "Specificare il nome dell'alegato (Pdf/Word)", vbCritical Or vbOKOnly, Caption
        TXT_FILE.SetFocus
        Exit Sub
    End If
    
    If (RTrim(TXT_NUMERO.Text) <= "") Then
        MsgBox "Specificare il numero telefono", vbCritical Or vbOKOnly, Caption
        TXT_NUMERO.SetFocus
        Exit Sub
    End If
    
    If (CHK_COVER.value = 1) Then
        If (RTrim(TXT_COVER.Text) <= "" Or Not FileExists(TXT_COVER.Text)) Then
            MsgBox "Specificare una cover", vbCritical Or vbOKOnly, Caption
            TXT_COVER.SetFocus
            Exit Sub
        End If
    End If

    Set objFaxServer = CreateObject("FaxServer.FaxServer")
    objFaxServer.Connect (TXT_SERVER.Text)
    Set objFaxDoc = objFaxServer.CreateDocument(TXT_FILE.Text)
    
    objFaxDoc.FaxNumber = TXT_NUMERO.Text
    objFaxDoc.RecipientName = TXT_DESTINATARIO.Text
    
    If (CHK_COVER.value = 1) Then
        objFaxDoc.SendCoverPage = 1
        objFaxDoc.CoverPageName = TXT_COVER.Text
        objFaxDoc.CoverPAgeSubject = TXT_OGGETTO.Text
        objFaxDoc.CoverPageNote = TXT_NOTE.Text
    End If
    objFaxDoc.Send
       
    Set objFaxDoc = Nothing
    
    objFaxServer.Disconnect
    
    Set objFaxServer = Nothing
Exit Sub
ErrTrap:
    Select Case MsgBox("Errore:(" & Err.Number & ")" & Err.Description, vbAbortRetryIgnore Or vbCritical, Caption)
        Case vbRetry
            Resume
        Case vbAbort
            If (Not objFaxDoc Is Nothing) Then Set objFaxDoc = Nothing
            If (Not objFaxServer Is Nothing) Then Set objFaxServer = Nothing
            Exit Sub
        Case vbIgnore
            Resume Next
    End Select

End Sub

Private Sub Command3_Click()
CommonDialog.Filter = "Documenti Word|*.doc|Acrobat reader|*.pdf"
CommonDialog.ShowOpen
TXT_FILE.Text = CommonDialog.FileName
End Sub

Private Sub Command2_Click()
CommonDialog.Filter = "Cover Pages|*.cov"
CommonDialog.ShowOpen
TXT_COVER.Text = CommonDialog.FileName

End Sub

Private Sub Form_Load()

TXT_SERVER.Text = GetSetting(App.EXEName, "INPUT", "SERVER")
If (RTrim(TXT_SERVER.Text) <= "") Then
    TXT_SERVER.Text = ComputerName
End If
TXT_FILE.Text = GetSetting(App.EXEName, "INPUT", "FILE")
TXT_NUMERO.Text = GetSetting(App.EXEName, "INPUT", "NUMERO")
CHK_COVER.value = 0
DisabilitaControlli False
End Sub

Private Sub Form_Unload(Cancel As Integer)
    
    SaveSetting App.EXEName, "INPUT", "SERVER", TXT_SERVER.Text
    SaveSetting App.EXEName, "INPUT", "FILE", TXT_FILE.Text
        SaveSetting App.EXEName, "INPUT", "NUMERO", TXT_NUMERO.Text

End Sub


Manipolare un documento Word da Visual Basic


Codice utile per aprire o creare un modello di Word da Visual Basic e inserirvi del testo passato dall’applicazione VB. Anzitutto è necessario creare un file modello chiamandolo appunto modello.dot e creare all'interno di esso 4 bookmark di nome a,b,c,d. Creare poi in vb un form con tre campi di testo e 6 pulsanti ed incollare il codice seguente.
Tip fornito dal sig. C.Calabrò


Private Sub Command1_Click() On Error GoTo Errore 'definisce che oggetto è objWord (in questo caso è una nuova applicazione Word) Dim objWord As Word.Application 'definisce che oggetto è objDoc (in questo caso è un nuovo documento Word) Dim objDoc As Word.Document 'ora che objWord è dichiarato si vuole effettivamente 'aprire questa nuova applicazione Word Set objWord = New Word.Application 'ora che objDoc è dichiarato si vuole effettivamente 'aprire questo nuovo documento Set objDoc = objWord.Documents.Add(app.path & "\Modello.dot") 'si rende visibile Word objWord.Visible = True 'rende attivo il documento appena creato objDoc.Activate objDoc.Save Errore: MsgBox "Il salvataggio è necessario", vbExclamation, "Cristiano Calabrò" End Sub Private Sub Command2_Click() Dim objWord As Word.Application Dim objDoc As Word.Document Set objWord = New Word.Application Set objDoc = objWord.Documents.Add(App.Path & "\Modello.dot") objWord.Visible = True objDoc.Activate objDoc.Bookmarks("a").Range = Text1.Text objDoc.Bookmarks("b").Range = Text2.Text objDoc.Bookmarks("c").Range = Text3.Text objDoc.Bookmarks("d").Range = Date & " - Segnalibro d" objDoc.PrintPreview End Sub Private Sub Command4_Click() Dim objWord As Word.Application Dim objDoc As Word.Document Set objWord = New Word.Application Set objDoc = objWord.Documents.Add(App.Path & "\Modello.dot") objWord.Visible = True objDoc.Activate objDoc.PrintOut objWord.Quit (False) End Sub Private Sub Command5_Click() Dim objWord As Word.Application Dim objDoc As Word.Document Set objWord = New Word.Application Set objDoc = objWord.Documents.Add objWord.Visible = True objDoc.Activate objDoc.Save End Sub Private Sub Doc_Click() Dim objWord As Word.Application Dim objDoc As Word.Document Set objWord = New Word.Application Set objDoc = objWord.Documents.Add objWord.Visible = True objDoc.Activate End Sub Private Sub Form_Load() Text1.Text = "Segnalibro a" Text2.Text = "Segnalibro b" Text3.Text = "Segnalibro c" End Sub Private Sub Mod_Click() Dim objWord As Word.Application Dim objDoc As Word.Document Set objWord = New Word.Application Set objDoc = objWord.Documents.Open(App.Path & "\Modello.dot") objWord.Visible = True objDoc.Activate End Sub