Sviluppo4d.it
Sito indipendente di informazioni tecniche per sviluppatori 4th Dimension italiani  

Sviluppatori 4D

Utility 4D

Risorse 4D



4d logo
Naviga:

Faq

Ho trovato 76 faq.

Categoria Argomento Commenti
Codice Codice Controllo Codice Fiscale
Questo metodo ritorna Vero se il codice fiscale passato è scritto correttamente, utilizzando il carattere di controllo finale. La procedura è un po' condensata: per l'algoritmo di controllo completo potete trovare il dettaglio sul sito del Ministero delle Finanze.

    `Metodo Controllo_CodiceFiscale
    `controlla il checksum del codice fiscale
    `Nexus srl 4-6-90
C_LONGINT($i;$n_l;$car_l;$cod_l)
C_STRING(16;$cf_s;$1)
C_STRING(43;$mysndcod_s)
$cf_s:=$1
If (Length($cf_s)#16)
  $0:=False
Else
  $n_l:=0
  For ($i;2;14;2)
    $car_l:=Ascii($cf_s[[$i]])
    Case of
      : (($car_l>=48) & ($car_l<=57))
        $cod_l:=$car_l-48
      : (($car_l>=65) & ($car_l<=90))
        $cod_l:=$car_l-65
      Else
        $cod_l:=0
    End case
    $n_l:=$n_l+$cod_l
  End for
  $mysndcod_s:="BAFHJNPRTVUMBERTOBAFHJNPRTVCESULDGIMOQKWZYX"
  For ($i;1;15;2)
    $car_l:=Ascii($cf_s[[$i]])-47
    $cod_l:=Ascii($mysndcod_s[[$car_l]])-65
    $n_l:=$n_l+$cod_l
  End for
  $0:=((65+$n_l-(Int($n_l/26)*26))=Ascii($cf_s[[16]]))
End if
3
Info Info JSON e i caratteri da filtrare
Nelle stringhe JSON i caratteri da filtrare sono:

virgolette (quote) -> \"
barra a destra (slash) -> \/
barra a sinistra (backslash) -> \\
backspace -> \b
formfeed -> \f
nuova linea (new line, char(10) ) -> \n
a capo (return, char(13) ) -> \r
tabulatore (tab, char(9) ) -> \t
tutti i caratteri da 0 a 31 esclusi quelli sopra devono diventare \x00-\x1F
un qualsiasi carattere unicode -> \u+4 cifre esadecimale


// web_jsonEncode

$risultato:=$1

$risultato:=Replace string($risultato;"\\";"\\\\")
$risultato:=Replace string($risultato;char(double quote);"\\\"")
$risultato:=Replace string($risultato;"/";"\\/")
$risultato:=Replace string($risultato;Char(Backspace);"\\b")
$risultato:=Replace string($risultato;Char(FF ASCII code);"\\f")
$risultato:=Replace string($risultato;Char(Line feed);"\\n")
$risultato:=Replace string($risultato;Char(Carriage return);"\\r")
$risultato:=Replace string($risultato;Char(Tab);"\\t")

$0:=$risultato
1
Tecniche Tecniche Duplicazione RECORD con SUBRECORD
Le nuove versioni di 4D non duplicano piu' i subrecord all'interno del record ed il campo id_added_by_converter non e' editabile, ne avevo necessita' per cui ho fatto questa routine (spero esista un metodo piu' semplice)

Occorre preventivamente creare un set del record da duplicare ed un set del record duplicato (ricordarsi di cancellarli al termine) poi :

DuplicaSubrecords (->[TABLE];->[TABLE]Subrecord;->[TABLE_Subrecord];->[TABLE_Subrecord]id_added_by_converter)


    // DUPLICAZIONE SUBRECORDS

$p_TABLErecord:=$1 // Puntatore alla Tabella RECORD
$p_TABLEsubrecord:=$2 // Puntatore al campo SUBRECORD DEL RECORD
$p_TABLENewsubrecord:=$3 // Puntatore alla Tabella NEW SUBRECORD
$p_Id:=$4 // Puntatore al campo id_added_by_converter

$NumeroTABLE:=Table($p_TABLENewsubrecord)
USE SET("OLD") // Richiamo il record originale
QUERY($p_TABLENewsubrecord->;$p_Id->=Get subrecord key($p_TABLEsubrecord->))
$NumeroSubrecords:=Records in selection($p_TABLENewsubrecord->)
If ($NumeroSubrecords>0)
  USE SET("NEW") // Richiamo il record copia
  For ($i;1;$NumeroSubrecords)
    CREATE SUBRECORD($p_TABLEsubrecord->) // Creo l'aggancio al record
  End for
  SAVE RECORD($p_TABLErecord->)
  USE SET("OLD")
  $NumeroCampi:=Get last field number($p_TABLENewsubrecord)
  ARRAY POINTER($p_ElementoCampo;$NumeroSubrecords*$NumeroCampi)
  For ($i;1;$NumeroSubrecords)
    $P_RECORD:=($i-1)*$NumeroCampi
    For ($k;1;$NumeroCampi)
      $P_Vettore:=$P_RECORD+$k // Calcolo l'elemento del vettore
      $p_ElementoCampo{$P_Vettore}:=Get pointer("$var_"+String($k)) // Associo il puntatore
      $p_Campo:=Field($NumeroTABLE;$k) // Puntatore al campo da prelevare
      $p_ElementoCampo{$P_Vettore}->:=$p_Campo-> // Momorizzo il valore del campo sulla variabile
    End for
    NEXT RECORD($p_TABLENewsubrecord->)
  End for
  USE SET("NEW")
  QUERY($p_TABLENewsubrecord->;$p_Id->=Get subrecord key($p_TABLEsubrecord->))
  $NumeroSubrecords:=Records in selection($p_TABLENewsubrecord->)
  ON ERR CALL("ErrorIdSubrecord") // Filtra Errore su assegnazione campo id_added_by_converter (Metodo ErrorIdSubrecord VUOTO)
  For ($i;1;$NumeroSubrecords)
    $P_RECORD:=($i-1)*$NumeroCampi
    For ($k;1;$NumeroCampi)
      $P_Vettore:=$P_RECORD+$k // Calcolo l'elemento del vettore
      $p_Campo:=Field($NumeroTABLE;$k) // Puntatore al campo da assegnare
      $p_Campo->:=$p_ElementoCampo{$P_Vettore}-> // Assegno il valore dalla variabile al campo
    End for
    SAVE RECORD($p_TABLENewsubrecord->)
    NEXT RECORD($p_TABLENewsubrecord->)
  End for
  UNLOAD RECORD($p_TABLENewsubrecord->)
  ON ERR CALL("")
  SAVE RECORD($p_TABLErecord->) // Forse non serve
End if
2
Info Info Limitare il numero di caratteri in una variabile alfanumerica
Una delle prime FAQ pubblicate su Sviluppo4D riguardava la limitazione del numero di caratteri inseribili in un campo Alpha.

Eccone una versione aggiornata:
Case of
      : (Form event=On After Edit)
      If (Length(Get edited text)>=vLength)
           $textvariable:=Substring(Get edited text;1;vLength)
      End if
End case

A vLength può essere sostituita la lunghezza del campo, nei casi in cui è possibile.

A $textvariable potrebbe essere sostituito Self->, ma in questo caso il metodo non funziona ad esempio sugli elementi degli array di una listbox.
1
Codice Codice Come creare una plist per Mac OS X o IOS
Il formato XML plist è lo standard con cui sono scritte ad esempio le preferenze dei vari programmi su Mac OS X.

Il formato è letto nativamente dalle applicazioni scritte in XCode, come ad esempio programmi per iPhone e iPad.

L'esempio successivo mostra come creare una plist per ad esempio inviare dei dati strutturati ad un applicativo su iOS in modo semplice e veloce: infatti un xml generico andrebbe ogni volta interpretato, mentre la plist può essere letta direttamente come un NSDictionary.

    ` ----------------------------------------------------
    ` User name (OS): Umberto Migliore
    ` Date and time: 08-02-11, 12:22:51
    ` ----------------------------------------------------
    ` Method: nx_crea_plist
    ` Description:
    `mostra come creare un documento plist:
    `
    `<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
    `<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    `<plist version="1.0">
    ` <dict>
    ` <key>Author</key>
    ` <string>William Shakespeare</string>
    ` <key>Title</key>
    ` <string>Macbeth</string>
    ` <key>Lines</key>
    ` <array>
    ` <string>It is a tale told by an idiot,</string>
    ` <string>Full of sound and fury, signifying nothing.</string>
    ` </array>
    ` <key>Birthdate</key>
    ` <integer>1564</integer>
    ` </dict>
    `</plist>
    `
    ` Parameters
    ` ----------------------------------------------------
C_TEXT($autore;$titolo)
C_LONGINT($annonascita)
ARRAY TEXT($citazione;0)

    `=== preparo i dati
$autore:="William Shakespeare"
$titolo:="Macbeth"
$annonascita:=1564
APPEND TO ARRAY($citazione;"It is a tale told by an idiot,")
APPEND TO ARRAY($citazione;"Full of sound and fury, signifying nothing.")

    `=== creo la plist
$xml_ref:=DOM Create XML Ref("plist";"";"version";"1.0")

    `=== dict principale che contiene tutto
$dict:=DOM Create XML element($xml_ref;"dict")

$key:=DOM Create XML element($dict;"key")
DOM SET XML ELEMENT VALUE($key;"Author")
$value:=DOM Create XML element($dict;"string")
DOM SET XML ELEMENT VALUE($value;$autore)

$key:=DOM Create XML element($dict;"key")
DOM SET XML ELEMENT VALUE($key;"Title")
$value:=DOM Create XML element($dict;"string")
DOM SET XML ELEMENT VALUE($value;$titolo)

$key:=DOM Create XML element($dict;"key")
DOM SET XML ELEMENT VALUE($key;"Lines")
$array:=DOM Create XML element($dict;"array")
For ($riga;1;Size of array($citazione))
  $value:=DOM Create XML element($array;"string")
  DOM SET XML ELEMENT VALUE($value;$citazione{$riga})
End for

$key:=DOM Create XML element($dict;"key")
DOM SET XML ELEMENT VALUE($key;"Birthdate")
$value:=DOM Create XML element($dict;"integer")
DOM SET XML ELEMENT VALUE($value;$annonascita)

    `=== chiude l'xml, aggiunge lo header e ritorna un testo
DOM EXPORT TO VAR($xml_ref;$testo)
DOM CLOSE XML($xml_ref)
$header:="<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
$testo:=Insert string($testo;$header;Position("<plist";$testo))

ALERT($testo)  ` $0:=$testo
1
Codice Codice Ruotare un'immagine usando SVG
Questo codice è un esempio di utilizzo del componente incluso in 4d per gestire i comandi SVG; lo scopo del metodo è di ruotare di 90 gradi un'immagine, ad esempio per raddrizzare una foto.

    // ----------------------------------------------------
    // User name (OS): Umberto Migliore
    // Date and time: 14-02-11, 11:41:14
    // ----------------------------------------------------
    // Method: nx_svgRuotaQuartoDestra
    // Description
    // Ruota un immagine di un quarto di giro a destra
    //
    // Parameters
    // ----------------------------------------------------

C_PICTURE($immagine;$1;$0)
$immagine:=$1
PICTURE PROPERTIES($immagine;$larga;$alta)
$maggiore:=Choose($larga>$alta;$larga;$alta)
$svg:=SVG_New ($alta;$larga)
$img:=SVG_New_embedded_image ($svg;$immagine;0;0)
SVG_SET_TRANSFORM_ROTATE ($svg;90;$maggiore/2;$maggiore/2)
If ($larga>$alta)
  SVG_SET_TRANSFORM_TRANSLATE ($svg;0;$larga-$alta)
End if
$immagine:=SVG_Export_to_picture ($svg;0)
SVG_CLEAR ($svg)
$0:=$immagine
1
Codice Codice Data e ora in formato XML
Il formato XML di data e ora è il seguente AAAA-MM-GGTHH:MM:SS.

Il vantaggio di questa stringa è che è ordinabile, contiene la coppia dei dati e quindi è più leggibile del timestamp (che rimane però più efficiente e consuma meno spazio su disco e in memoria come indice).

Ecco alcuni trucchi per convertire una data in questo formato e viceversa (non documentati, mi sembra) in 4d 2004.3:

Date("2006-01-24T00:00:00") -> ritorna effettivamente la data 24 gen 2006: Importante funziona solo se la stringa è lunga 19 caratteri e la data è seguita dal separatore "T".

String(current date;8) -> ritorna la data nel formato XML completa di separatore = "2006-01-24T00:00:00"

Per avere data e ora si può usare questa semplice riga:

Replace string(String(Current date;8);"00:00:00";String(Current time;1))

1
Info Info Sintassi 4D SQL : INNER JOIN
Una inner join crea una griglia di dati combinando i valori delle due tabelle di partenza (A and B) basandosi su una certa regola di confronto: la query compara ogni riga della tabella A con ciascuna riga della tabella B cercando di soddisfare la regola di confronto definita.

Esempio, date queste due tabelle di dati:

Tabella Aziende
ID_AziendaRagione_Sociale
az1Nexus
az2Acme
az3NewCo


Tabella Contatti
CognomeID_Azienda
Rossiaz1
Verdiaz2
Bianchi-


Begin SQL
    SELECT Cognome,Aziende.Ragione_Sociale
    FROM Contatti
    INNER JOIN Aziende
    ON Contatti.ID_Azienda=Aziende.ID_Azienda
    INTO :ArrCognome,:ArrRagSociale;
End SQL

Risultato:
CognomeRagione_Sociale
RossiNexus
VerdiAcme
1
Codice Codice Modificare la cella di una listbox con un solo clic
Per modificare l'elemento di una list box è necessario cliccarci due volte: il primo clic seleziona l'elemento, il secondo lo rende modificabile. Per fare in modo che un clic renda direttamente modificabile l'elemento si può uasre il seguente codice:

Case of
: (Form event=On Clicked )
    ` mi asssicuro che non stia facendo una selezione mutipla
      If (Not(Shift down | Windows Ctrl down))
           LISTBOX GET CELL POSITION(*;"ListBox";col;row;colVar_p)
           EDIT ITEM(colVar_p->;row)
      End if
End case


1
Info Info Nomi di variabili riservati
I seguenti nomi di variabili sono riservati a 4D:

C1, C2, C3, C4, C5, ecc. (usate nei report)
OK
Document
Error
KeyCode
Modifiers
MouseDown
MouseProc
MouseX
MouseY
FldDelimit
RecDelimit


Non devono dunque essere usate se non nel contesto cui si riferiscono: ad esempio Document contiene il percorso del documento dopo aver usato Open document, Create document o Append document ed è stato scelto un file mostrando la dialog di sistema per l'apertura o il salvataggio di un file.
1
Comandi Comandi [v11 SQL] Il comando SET QUERY AND LOCK
Il nuovo comando SET QUERY AND LOCK, che prende come parametro semplicemente True o False, permette di richiedere il blocco dei record risultanti da una query. Ciò garantisce che i risultati di una certa ricerca non possano essere modificato da un altro processo che non sia quello attuale.

Il comando può essere usato solo all'interno di una transazione (altrimenti restituisce errore), e i record restano bloccati finché la transazione viene terminata: a quel punto i record vengono comunque rilasciati. Basta comunque chiamare SET QUERY AND LOCK(False) per rilasciarli.

Ecco un esempio di cancellazione controllata da SET QUERY AND LOCK:

START TRANSACTION
SET QUERY AND LOCK(True)`così mi assicuro che i record trovati siano locked per gli altri
QUERY([Clients];[Clients]Category=“C”)
DELETE SELECTION([Clients])
SET QUERY AND LOCK(False)
VALIDATE TRANSACTION

1
Codice Codice Metodo EliminaSpazi con Match Regex
Versione del metodo che elimina gli spazi dall'inizio e dalla fine di una stringa usando il comando Match Regex e due semplici regular espressions.

C_TEXT($miaStringa;$1)
C_TEXT($0;$risultato)
C_TEXT($pattern)
C_LONGINT($inizio;$dove;$lunga)
C_BOOLEAN($trovato)
$miaStringa:=$1
$inizio:=1
$foundFlag:=False

    `pattern regex per gli spazi all'inizio
    `^ -- indica l'inizio da dove cercare
    `\s+ -- search for one or more white spaces
$pattern:="^\\s+"

$trovato:=Match regex($pattern;$miaStringa;$inizio;$dove;$lunga)
If ($trovato)
$miaStringa:=Substring($miaStringa;$lunga+1)
End if
    `pattern regex per gli spazi alla fine della stringa
    `$ -- indica la fine dove cercare
$pattern:="\\s+$"

$trovato:=Match regex($pattern;$miaStringa;$inizio;$dove;$lunga)
If ($trovato)
$miaStringa:=Substring($miaStringa;$inizio;$dove-1)
End if
$0:=$miaStringa
1
Info Info [v11 SQL] Dove si trovano i manuali?
Dalla versione v11 i manuali non vengono più installati con le applicazioni.

Questo è l'indirizzo dove trovare i manuali di 4d in inglese:
http://www.4d.com/support/documentation.html

Per chi vuole consultare la guida online, l'indirizzo è:
http://www.4d.com/docs/4DDOCUS.HTM

Per configurare il percorso dell'help richiamabile con il tasto F1 nelle preferenze va scritto questo:
http://www.4d.com/docs/

2
Tecniche Tecniche Accedere ad un database 4D
"io ho la necessità di collegarmi ad un database 4d (che gira su piattaforma Mac) da un server MSSQL per estrarre e pubblicare alcuni dati.
Potete spiegarmi la procedura per poter effettuare questa operazione?"

Risponde Umberto Migliore:
Ci sono diverse possibilità:
  • se sul server 4d è presente la licenza web si può preparare una chiamata in GET o POST che ritorni i valori in un formato elaborabile (tipo server REST)
  • se è presente la licenza WebService si può fare una chiamata SOAP usando l'indirizzo automatico http://indirizzoserver/4DWSDL
  • se si vuole accedere alle tabelle direttamente si può usare una chiamata ODBC dopo aver installato il corrispondente driver ODBC (disponibile gratuitamente)
  • via PHP utilizzando il driver PDO_4D incluso nelle ultime release di PHP


Diciamo che dipende dal tipo di informazioni che si vogliono passare, con che frequenza e con che controllo di validità o se servono eventuali elaborazioni a monte.
8
Codice Codice Conversione da esadecimale a decimale
Passando come parametro una stringa in forma esadecimale al seguente metodo, questo restituisce il valore decimale relativo:

C_TEXT($CifraEsadecimale_t;$tutteLeCifre_t;$1;$NumEsadecimale_t)
C_LONGINT($0;$posizione_l)
$0:=0
$tutteLeCifre_t:="0123456789ABCDEF"
$NumEsadecimale_t:=$1
While (Length($NumEsadecimale_t)>0)
          $CifraEsadecimale_t:=Substring($NumEsadecimale_t;0;1)
          $NumEsadecimale_t:=Substring($NumEsadecimale_t;2;Length($NumEsadecimale_t))
          $0:=$0*16
          $posizione_l:=Position($CifraEsadecimale_t;$tutteLeCifre_t)-1
          $0:=$0+$posizione_l
End while



2
Info Info [v11 SQL] Modifiche al comando QUERY BY FORMULA
Con la v11 SQL i comandi QUERY BY FORMULA e QUERY SELECTION BY FORMULA richiedono obbligatoriamente come parametro la tabella su cui eseguire la query.

Come già detto, per migliorare le prestazioni questi comandi vengono eseguiti sul Server quando vengono eseguiti da un Client. Inoltre è stato implementato un sistema di ottimizzazione delle QUERY BY FORMULA per migliorarne ulteriormente le prestazioni.
1
Codice Codice Come usare le transazioni nelle maschere di inserimento V2
Un altro schema per l'uso delle transazioni nell'inserimento o nella modifica di un record:

Metodo del Form di inserimento


Case of
  : (Form Event=On Load)
    START TRANSACTION
    ....

  : (Form Event=On Validate)
    VALIDATE TRANSACTION
    ....

  : (Form Event=On Unload)
    If (In transaction)
      CANCEL TRANSACTION
    End if

End case

Da ricordare che il form event On Unload di default non è attivo per il form e dunque è da attivare manualmente.
1
Tecniche Tecniche Lanciare una stored in 4d 2004 *
Nella versione 11 è possibile impostare un flag per cui un metodo verrà lanciato in automatico sul server (dove in alcune condizioni le cose sono molto più veloci); il processo resterà in attesa del metodo e ne userà il risultato.

Per ottenere la stessa cosa in 2004 dobbiamo fare in modo che il client attenda la fine del processo sul server per leggere la risposta e la stored invece invece alla fine dell'esecuzione deve prima di chiudersi aspettare che il client abbia la risposta.
Ecco un metodo che si può usare come base di lavoro:

=== SUL CLIENT:
C_BLOB(blob_risposta)
$id:=Execute on server("metodo_suserver";128*1024;"metodo")
nexus_stored("attendi";$id)
  ` ... qui posso usare la risposta



=== SUL SERVER:
nexus_stored("start")
  ` ... qui va il tuo codice che scrive la risposta in un blob, ad esempio
nexus_stored("stop")



=== ECCO IL METODO BASE:
    ` Method nexus_stored
    ` Nexus srl, www.nexusonline.it

Case of
  : ($1="start")  ` === startup del processo
    If (Application type=4D Server )
      C_BOOLEAN(stored_finito;client_letto)
      stored_finito:=False
      client_letto:=False
        C_BLOB(blob_risposta)
        SET BLOB SIZE(blob_risposta;0)
    End if
    
  : ($1="stop")  ` === chiusura processo
    If (Application type=4D Server )
      client_letto:=False
      stored_finito:=True
      $start:=Milliseconds
      While (Not(client_letto) & ((Milliseconds-$start)<30000))
        DELAY PROCESS(Current process;1)
      End while
    End if
    
  : ($1="attendi")  ` === legge la risposta dalla stored e la chiude
    C_BOOLEAN(stored_finito;processo_finito;client_letto)
    C_TEXT(currentProgressStatus)
    $pid:=$2
    processo_finito:=False
    Repeat
      DELAY PROCESS(Current process;10)
      GET PROCESS VARIABLE($pid;stored_finito;processo_finito)
    Until (processo_finito)
    GET PROCESS VARIABLE($pid; blob_risposta; blob_risposta)
    client_letto:=True
    SET PROCESS VARIABLE($pid;client_letto;client_letto)
End case
1
File File Metodo Benchmark v1.2.1*
Contiene una struttura dove propongo una base di benchmark delle versioni di 4D e delle piattaforme su cui viene lanciato.

In questo momento il codice è abbastanza approssimativo e non pesa allo stesso modo le varie parti del test (Export e Import sono sicuramente più significative delle altre funzioni in questo modo), inoltre testa solo il db engine del 4d mono, quindi create record, indexing, query, sort.

    `Method Benchmark
    `version 1.2.2 - 5 feb 2009
DEFAULT TABLE([Table])
If (Records in table>0)
  ALERT("You should launch this one on a new db")
  ALL RECORDS
  DELETE SELECTION
  FLUSH BUFFERS
Else
  $quantity:=Num(Request("How many record?";String(1000)))
  If (ok=1)
    $start:=Tickcount
    $firstStart:=$start
    `create record
    For ($i;1;$quantity)
      CREATE RECORD
      [Table]First:=String($i)
      For ($j;1;10)  `tre lettere
        [Table]Second:=[Table]Second+Char((Random%(122-97+1))+97)
      End for
      [Table]Numeric:=Random*Random
      SAVE RECORD
    End for
    FLUSH BUFFERS
    $benchmark_create:=Tickcount-$start
    $start:=Tickcount
    For ($i;1;$quantity)
      MESSAGE(String($i)+" on "+String($quantity))
      CREATE RECORD
      [Table]First:=String($i)
      For ($j;1;10)
        [Table]Second:=[Table]Second+Char((Random%(122-97+1))+97)
      End for
      [Table]Numeric:=Random*Random
      SAVE RECORD
    End for
    FLUSH BUFFERS
    $benchmark_createWithDialog:=Tickcount-$start
    $start:=Tickcount
    ALL RECORDS([Table])
    EXPORT TEXT([Table];"testexport.txt")
    $benchmark_export:=Tickcount-$start
    $start:=Tickcount
    IMPORT TEXT([Table];"testexport.txt")
    FLUSH BUFFERS
    $benchmark_import:=Tickcount-$start
    $start:=Tickcount
    SET INDEX([Table]First;True)
    $benchmark_index:=Tickcount-$start
    $start:=Tickcount
    QUERY([Table];[Table]First>"4")
    $benchmark_queryMedium:=Tickcount-$start
    $start:=Tickcount
    QUERY([Table];[Table]First<"9")
    $benchmark_queryLarge:=Tickcount-$start
    $start:=Tickcount
    QUERY([Table];[Table]First<"51";*)
    QUERY([Table]; & ;[Table]Second>"M")
    $benchmark_queryDouble:=Tickcount-$start
    $start:=Tickcount
    ORDER BY([Table];[Table]First;>)
    $benchmark_orderSingle:=Tickcount-$start
    $start:=Tickcount
    ORDER BY([Table];[Table]Second;>;[Table]First;<)
    $benchmark_orderDouble:=Tickcount-$start

    $benchmark_global:=Tickcount-$firstStart

    If (Compiled application)
      $compiled:=" Comp"
    Else
      $compiled:=" Inter"
    End if
    $result:="GLOBAL mm:ss:tt ["+String($quantity)+$compiled+"] "
    $result:=$result+Time string($benchmark_global/60)+", "+String($benchmark_global)+"tick"+Char(13)+Char(Line feed )
    ALERT($result)
    $result:=$result+"create "+Time string($benchmark_create/60)+", "+String($benchmark_create)+"tick"+Char(13)+Char(Line feed )
    $result:=$result+"withDialog "+Time string($benchmark_createWithDialog/60)+", "+String($benchmark_createWithDialog)+"tick"+Char(13)+Char(Line feed )
    $result:=$result+"export "+Time string($benchmark_export/60)+", "+String($benchmark_export)+"tick"+Char(13)+Char(Line feed )
    $result:=$result+"import "+Time string($benchmark_import/60)+", "+String($benchmark_import)+"tick"+Char(13)+Char(Line feed )
    $result:=$result+"index "+Time string($benchmark_index/60)+", "+String($benchmark_index)+"tick"+Char(13)+Char(Line feed )
    $result:=$result+"qryMedium "+Time string($benchmark_queryMedium/60)+", "+String($benchmark_queryMedium)+"tick"+Char(13)+Char(Line feed )
    $result:=$result+"qryLarge "+Time string($benchmark_queryLarge/60)+", "+String($benchmark_queryLarge)+"tick"+Char(13)+Char(Line feed )
    $result:=$result+"qryDouble "+Time string($benchmark_queryDouble/60)+", "+String($benchmark_queryDouble)+"tick"+Char(13)+Char(Line feed )
    $result:=$result+"orderSingle "+Time string($benchmark_orderSingle/60)+", "+String($benchmark_orderSingle)+"tick"+Char(13)+Char(Line feed )
    $result:=$result+"orderDouble "+Time string($benchmark_orderDouble/60)+", "+String($benchmark_orderDouble)+"tick"+Char(13)+Char(Line feed )
    SET TEXT TO CLIPBOARD($result)
    C_BLOB($BLOB)
    TEXT TO BLOB($result;$BLOB;3)
    $vhDocRef:=Create document("";"txt")  ` Save the document of your choice
    If (OK=1)  ` If a document has been created
      CLOSE DOCUMENT($vhDocRef)  ` We don't need to keep it open
      BLOB TO DOCUMENT(Document;$BLOB)
      ` Write the document contents
    End if
  End if
End if
1
Tecniche Tecniche Importare un campo boolean da un file di testo
Facendo un import di dati from file con un campo booleano ho provato sia con true (prima lettera minuscola) che con 1 ma alla fine ho scoperto che era sufficiente scrivere True con la prima lettera maiuscola.
Versione 2004 7.
1
Codice Codice Generazione automatica del file Sitemap.xml
Se avete un sito dinamico, dove non tutti i link sono facilmente raggiungibili dai motori di ricerca, è utile comunicare agli stessi l'elenco degli indirizzi disponibili con un protocollo chiamato sitemap.

L'indicazione dell'esistenza della sitemap viene comunicata al motore di ricerca o tramite una loro pagina dedicata (come Google) oppure più genericamente con una riga nel file robots.txt (vedi ad esempio la faq Generazione automatica del file Robots.txt dove è descritto il file robots di Sviluppo4d.it).

Clicca qui per vedere il risultato.

`metodo web_sitemap

$eol:="\r\n"
$txt:=""

$txt:=$txt+"<?xml version='1.0' encoding='UTF-8'?>"+$eol
$txt:=$txt+"<urlset xmlns=\"http://www.google.com/schemas/sitemap/0.84\" "
$txt:=$txt+"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
$txt:=$txt+"xsi:schemaLocation=\"http://www.google.com/schemas/sitemap/0.84 "
$txt:=$txt+"http://www.google.com/schemas/sitemap/0.84/sitemap.xsd\">"+$eol

  `preparo la parte iniziale e finale del singolo url
$s:="<url><loc>http://www.sviluppo4d.it" `qua va il nome del sito corrente
$e:="</loc></url>"+$eol

`prima elenchiamo gli indirizzi fissi
$txt:=$txt+$s+""+$e`indirizzo base del sito
$txt:=$txt+$s+wb_xmlEncode ("/Users")+$e`indirizzo fisso su sviluppo4d.it

`poi costruiamo l'elenco degli indirizzi dinamici
ALL RECORDS([News])
While (Not(End selection([News])))
  $txt:=$txt+$s+"/Detail_News_Display?id="+String([News]id)+"&title="+ wb_xmlEncode( wb_urlEncode ([News]Title))+$e
  NEXT RECORD([News])
End while
ALL RECORDS([Faq])
While (Not(End selection([Faq])))
  $txt:=$txt+$s+"/Detail_FAQ_Display?id="+String([Faq]id)+"&title="+ wb_xmlEncode( wb_urlEncode([Faq]Title))+$e
  NEXT RECORD([Faq])
End while

  `chiudiamo il tag principale
$txt:=$txt+"</urlset>"
SEND HTML TEXT($txt)
1
Codice Codice Calcolo del numero della settimana (2)
Un po' di tempo fa avevo letto un discussione sul calcolo del numero della settimana; mi è capitato di leggere la definizione dell'inizio anno in base alla quale l'anno inizia dal Lunedì della settimana che contiene il 4 gennaio ed ecco qui l'algoritmo corretto



xData:=Date(Request("Data";String(Current date)))

    ` ----------------------------------------------------
    ` User name (OS): llarosa
    ` Date and time: 12/01/09, 13:09:35
    ` ----------------------------------------------------
    ` Method: Calcolo numero settimana
    ` Description Ritorna la settimana dell'anno usando ISO 8601 standard
    ` ( l'anno parte dal Lunedi della settimana che contiene il 4 Gennaio)
    `
    ` Parameters
    ` ----------------------------------------------------

  ` calcolo il 4 di gennaio che giorno è -2 perchè la day number conta come primo giorno la domenica
Jan04DOW:=Day number(Date("04-01-"+String(Year of(xData))))-2
` avendo fatto -2 la domenica diventa -1 e la riporto a 6
Jan04DOW:=(Num(Jan04DOW=-1)*6)+(Num(Jan04DOW#-1)*Jan04DOW)
` calcolo la data del primo lunedi dell'anno
FirstMonday:=Date("04-01-"+String(Year of(xData)))-Jan04DOW
` se la data è inferiore al primo lunedi dell'anno allora appartengono all'ultima settimana dell'anno
` prima quindi calcolo il primo lunedi dell'anno precedente
If (xData<FirstMonday)
` come già descritto ma riferito all'anno precedente
  Jan04DOW:=Day number(Date("04-01-"+String(Year of(xData)-1)))-2
  Jan04DOW:=(Num(Jan04DOW=-1)*6)+(Num(Jan04DOW#-1)*Jan04DOW)
  FirstMonday:=Date("04-01-"+String(Year of(xData)-1))-Jan04DOW
End if
xWeek:=(Int((xData-FirstMonday)/7))+1 ` calcolo della settimana
End if

ALERT(String(xWeek))
3
Info Info [v11 SQL] Passaggio da subtable a tabelle
Nella nota precedente sull'argomento e' stata intrapresa la strada di creare una nuova tabella e trasportarvi i dati della vecchia subtable assegnandogli la relazione nuova.

Secondo me molto difficile da realizzare in quanto bisgna crearsi una pocedura che converta tutte le vecchie subtable in tablelle e poi eventualmente cancelli quelle vecchie inutilizzate.

Io credo di aver trovato un sistema più veloce.

Ho notato che il centenuto del campo in relazione non è altro che il numero del record della tabella in relazione + 1

Eliminate la relazione di tipo subtable (non più ricreabile), i campi ora assumono valore di longint.
Ora con una query potrete ottenere i record correlati tipo

$recnum:=Record number([Tabella_principale])+1
query([Tabella_relazione];[Tabella_relazione]id_added_by_converter=recnum)

Oppure

Ricreare la relazione tra i due campi e nel campo dell'archivio principale inserire il valore del numero del record +1

1
Info Info Alternativa al comando SEND HTTP REDIRECT
Il comando Send Http Redirect in pratica dice al browser che la pagina cercata è stata "temporaneamente" spostato su un altro indirizzo: il browser in modo trasparente all'utente e anche abbastanza velocemente va a cercare il nuovo indirizzo.

Il codice seguente simula la chiamata Send Http Redirect con codice 4d:

`Metodo web_sendHttpRedirect

C_TEXT($1; nuovo_url)
$nuovo_url:=$1

ARRAY TEXT($atHeaders;3)
ARRAY TEXT($atValues;3)
$atHeaders{1}:="X-VERSION"
$atValues{1}:="HTTP/1.0"
$atHeaders{2}:="X-STATUS"
$atValues{2}:="302 Moved Temporarily"
$atHeaders{3}:="Location"
$atValues{3}:=$nuovo_url
SET HTTP HEADER($atHeaders;$atValues)

SEND HTML TEXT($nuovo_url)

1
Info Info Le parentesi graffe sotto Win senza codice ASCII *
Programmando sotto Windows, per aprire e chiudere le parentesi graffe, solitamente premo il tasto ALT a sinistra della barra spaziatrice e scrivo sul tastierino numerico in sequenza le cifre 123125.

Risulta comunque scomodo sui portatili, dove l'accesso ai NumPad è solitamente condizionato o dall'utilizzo di una "Function key" o dall'attivazione dell'emulazione NumPad sulla tastiera tradizionale.

Recentemente, usando un compilatore Java (linguaggio di programmazione che fa largo uso di graffe), ho scoperto che esiste un altro modo per ottenere lo stesso risultato:
premere il tasto AltGr a destra della barra spaziatrice, il maiuscolo e i due tasti indicanti le parentesi quadre: anche così si ottiene {}

Ecco un elenco completo.

graffa apertagraffa chiusasistema
ALT_GR+7ALT_GR+0GNU Linux
ALT_GR+8ALT_GR+9GNU Linux
ALT+123ALT+125Microsoft Windows
ALT_GR+SHIFT+èALT_GR+SHIFT++Microsoft Windows - GNU Linux
ALT+CTRL+SHIFT+èALT+CTRL+SHIFT++Microsoft Windows
⌥⇧è⌥⇧+Mac OS (con il layout Italiano - Pro)

7
Info Info [v11 SQL] Quando il BLOB non passa il testo alla variabile
Sto ancora guardando se sia un bug o un problema del mio codice, intanto, per sicurezza, pubblico il workaround.

Mi capita, lavorando con file di testo Unicode, che il comando BLOB TO TEXT eseguito dopo il DOCUMENT TO BLOB mi restituisca un testo vuoto.

Per evitare questo problema, ho deciso di agire differentemente: in una offscreen area di 4DWrite apro il file; da qui trasferisco il testo nella variabile 4D che veniva lasciata vuota dal BLOB TO TEXT.
3
Novizi Novizi Scorciatoie da tastiera *
Ecco alcune scorciatoie utilizzabili da tastiera:

- Chiusura di tutte le finestre di design (eccetto la struttura): Alt+Clik su uno qualsiasi dei bottoni di chiusura.

- Chiusura di tutte le finestre di design passando alla modalità User o Custom: Shift mantre si cambia modalità.

- Aprire il metodo selezionato: Ctrl+p.

- Rinominare gli oggetti solo selezionabili: Ctrl+Clic sul nome.

- Copiare il testo selezionato in un posto specifico degli appunti: Ctrl+Shift+un numero da 1 a 9.

- Incollare il testo da un posto specifico degli appunti:Ctrl+un numero da 1 a 9.

- Selezionare tutti gli oggetti di uno stesso tipo in un form: Ctrl(Command su Mac)+clik su uno degli oggetti da selezionare.

- Selezionare/deselezionare tutti gli eventi relativi ad un oggetto: Ctrl(Command su Mac)+clik su un evento.

- Creare un subrecord: Ctrl(Command su Mac)+/ (questa impostazione è modificabile usando 4D Customizer Plus).


4
Novita' Novita' [v11 - Conferenza] SQL injection
Una delle maggiori novità della versione 11 di 4D è l'uso dell'SQL. E' però necessario fare attenzione ad gli inserimenti all'interno dell'ambiente web per creare stringhe SQL. Facciamo il seguente esempio.

Supponiamo di avere:

SELECT * FROM Contact WHERE Name = :vName

dove vName è una variabile proveniente dalla pagina web. Supponiamo che lo smaliziato utente web abbia scritto nella variabile vName

Pippo; DELETE * FROM Contact

Ci ritroveremmo la tabella totalmente svuotata.
1
Plugin Plugin 4D Chart: CT Chart arrays
CT Chart arrays crea un grafico a partire dai dati memorizzati in alcuni array.
La sintassi è:

CT Chart arrays (area; type; size; categoryArray; seriesArray; valuesArray)

dove "area" è l'area 4D Chart, "type" è il tipo di grafico, "size" è la dimensione iniziale del grafico, "categoryArray", "seriesArray", e "valuesArray" sono gli array contenenti x, y e z del nostro grafico.

I tipi di grafico passabili in "type" sono:

1 per il grafico di tipo Area
2 per il grafico di tipo Column
3 per il grafico di tipo Picture
4 per il grafico di tipo Line
5 per il grafico di tipo Scatter
6 per il grafico di tipo Pie
7 per il grafico di tipo Polar
8 per il grafico di tipo 2D XY
100 per il grafico di tipo 3D Column
101 per il grafico di tipo 3D Line
102 per il grafico di tipo 3D Area
103 per il grafico di tipo 3D Surface
104 per il grafico di tipo 3D Triangle
105 per il grafico di tipo 3D Spike

A "size" possono essere assegnati i valori

1 = Variabile
2 = Relativa alla finestra (Auto-Variable)
3 = Relativa al grafico (Auto-Document)

L'array "categoryArray" è l'array delle X
L'array "seriesArray" è l'array delle serie. In un grafico bidimensionale è mostrato nell'asse X, nei tridimensionali è la Y
L'array "valuesArray" è l'array contenente i valori.


1
Codice Codice Numeri da cifre a lettere
Prima di tutto complimenti per il sito, non solo perché è davvero bello ma perché si vede che c'è chi ci lavora, quindi complimenti a chi lo fa.

Mando un frammento di codice che ritengo interessante anche se forse non hamolte occasioni d'impiego; è un method che converte un valore numerico nella corrispondente stringa descrittiva in lettere, esempio 8519 =
"ottomilacinquecentodiciannove".

Non ho trovato nulla di già fatto per 4D (in italiano). La conversione avviene nel formato usuale per valori in euro con decimali, come si usa per gli assegni, per esempio "trecentoventi/23centesimi"; è modificabile e si
puo facilmente omettere o modificare la parte decimale.
E' abbastanza compatto, contrariamente a quanto io stesso avevo supposto accingendomi a scriverlo.

Uso: passare un valore di tipo reale e torna un tipo testo. Accetta valori
da 1 a 999.999.999, genera un messaggio di errore se si passa un valore fuori range.



C_REAL($1;$valore)
C_TEXT($0;$decimale;$stringa)

ARRAY INTEGER($base;8)
ARRAY TEXT($descrizione;3)
C_INTEGER($X;$gruppo;$valoreDecine)

ARRAY TEXT($nome_unità;9)
$nome_unità{0}:=""
$nome_unità{1}:="uno"
$nome_unità{2}:="due"
$nome_unità{3}:="tre"
$nome_unità{4}:="quattro"
$nome_unità{5}:="cinque"
$nome_unità{6}:="sei"
$nome_unità{7}:="sette"
$nome_unità{8}:="otto"
$nome_unità{9}:="nove"

ARRAY TEXT($nome_10_20;9)
$nome_10_20{0}:=""
$nome_10_20{1}:="undici"
$nome_10_20{2}:="dodici"
$nome_10_20{3}:="tredici"
$nome_10_20{4}:="quattordici"
$nome_10_20{5}:="quindici"
$nome_10_20{6}:="sedici"
$nome_10_20{7}:="diciassette"
$nome_10_20{8}:="diciotto"
$nome_10_20{9}:="diciannove"

ARRAY TEXT($nome_decine;10)
$nome_decine{0}:=""
$nome_decine{1}:="dieci"
$nome_decine{2}:="venti"
$nome_decine{3}:="trenta"
$nome_decine{4}:="quaranta"
$nome_decine{5}:="cinquanta"
$nome_decine{6}:="sessanta"
$nome_decine{7}:="settanta"
$nome_decine{8}:="ottanta"
$nome_decine{9}:="novanta"
$nome_decine{10}:="cento"

$decimale:=Replace string(String(Dec($1));"0,";"")
$decimale:=$decimale+("0"*Num(Length($decimale)=1))
If ($decimale="00") `è uno zero non lettera o
  $decimale:="zero"
End if
$valore:=Int($1)

If ($valore=0) | ($valore>=(10^9)) ` valori accettati per la parte intera da 1 a 999.999.999
  $0:="### ERRORE valore fuori range"
Else
  For ($X;8;0;-1) ` calcola le basi per gli esponenti da 0 a 8 - esempio 825 = 8*(10^2) + 2*(10^1) + 5*(10^0)
    $base{$X}:=Int($valore/(10^$X))
    $valore:=$valore-($base{$X}*(10^$X))
  End for
  $gruppo:=3 `elabora separatamente milioni, migliaia e unità, nell'ordine (si potrebbe anche procedere per ordine inverso, non cambia)
  For ($X;8;0;-3)
    If ($base{$X}=1)
      $descrizione{$gruppo}:="cento"
    Else
      $descrizione{$gruppo}:=$nome_unità{$base{$X}}+("cento"*Num($base{$X}>0))
    End if
    $valoreDecine:=$base{$X-1}*10+$base{$X-2}
    If ($valoreDecine=1) & ($base{$X}=0)
      $descrizione{$gruppo}:=$descrizione{$gruppo}+("unmilione"*Num($gruppo=3))+("mille"*Num($gruppo=2))+("uno"*Num($gruppo=1))
    Else
      If ($valoreDecine>10) & ($valoreDecine<20) ` se >10 e <20 usa i nomi unidici, dodici, ecc
        $descrizione{$gruppo}:=$descrizione{$gruppo}+$nome_10_20{($valoreDecine-10)*Num(($base{$X-1})>0)}
      Else `altrimenti usa i nomi delle decine + i nomi delle unità
        If ($base{$X-2}=1) | ($base{$X-2}=8) ` se nome unità inizia per vocale omette l'ultima vocale del nome delle decine (ventuno e non ventiuno)
          $stringa:=Substring($nome_decine{$base{$X-1}};1;Length($nome_decine{$base{$X-1}})-1)
        Else
          $stringa:=$nome_decine{$base{$X-1}}
        End if
        $descrizione{$gruppo}:=$descrizione{$gruppo}+$stringa+$nome_unità{$base{$X-2}}
      End if
      $descrizione{$gruppo}:=$descrizione{$gruppo}+(("milioni"*Num($gruppo=3))*Num($descrizione{$gruppo}#""))
      $descrizione{$gruppo}:=$descrizione{$gruppo}+(("mila"*Num($gruppo=2)*Num($descrizione{$gruppo}#"")))
    End if
    $gruppo:=$gruppo-1 `elabora il gruppo successivo
  End for
  $0:=$descrizione{3}+$descrizione{2}+$descrizione{1}+" e "+$decimale+" centesimi" `concatena i nomi dei 3 gruppi: milioni, migliaia, unità + i decimali
End if

1
Tecniche Tecniche Backup degli Utenti in un documento su disco
Già dalla versione 2004 è possibile fare un backup o trasferire gli utenti creati dall'Amministratore con i comandi USERS TO BLOB e BLOB TO USERS.

Ecco i due metodi da usare:

`Metodo Utenti_Registra
C_BLOB($utenti_blb)
USERS TO BLOB($utenti_blb)
$doc:=Create document("")
If (ok=1)
  CLOSE DOCUMENT($doc)
  BLOB TO DOCUMENT(Document;$utenti_blb)
  SHOW ON DISK(Document)
End if


`Metodo Utenti_Carica
C_BLOB($utenti_blb)
$doc:=Select document("";"*";"Seleziona il file di backup degli utenti";0)
If (ok=1)
  DOCUMENT TO BLOB(Document;$utenti_blb)
  BLOB TO USERS($utenti_blb)
End if
1
Novita' Novita' [v11 - Conferenza] Le "Nested transaction"
Con la v11 SQL è possibile utilizzare le transazioni annidate. Il seguente codice è ammesso:

START TRANSACTION
  CREATE RECORD([Tabella1])
  START TRANSACTION
    CREATE RECORD([Tabella2])
    SAVE RECORD([Tabella2])
  VALIDATE TRANSACTION
  [...]
CANCEL TRANSACTION

Alla fine l'ultimo Cancel annulla anche la creazione del record in Tabella2.
1
Info Info [v11 SQL] Da dove posso scaricare 4d ?
La versione di 4D v11 SQL è scaricabile principalmente tramite un installer di piccole dimensioni che scarica dai siti americano o francese l'ultima versione disponibile di quello che si seleziona.

Questa è la modalità consigliata e dovrebbe essere più sicura sia come aggiornamento che per velocità (alcune componenti interne ripetute sono scaricate una volta sola).

Gli Online installer si trovano qui:
http://www.4d.com/products/downloads/download-v11.html

Da notare che l'installer tiene in locale quello che è già stato scaricato.. quindi la sua dimensione dovrebbe automaticamente crescere. Alle successive installazioni dovrebbe scaricare solo le componenti eventualmente aggiornate nel frattempo.

Per chi invece volesse installare 4d su più macchine ottimizzando quindi il download, esiste la possibilità di scaricare i file completi, da qui:
http://www.4d.com/products/downloads/download-v11-FTP.html

I file completi sono circa 580MB nella versione Windows multilingua, e 180MB nella versione Inglese per Mac.


1
Codice Codice Contare le parole di un testo
Ecco un piccolo metodo per contare il numero di parole presenti in un testo passato come parametro. In maniera banale si contano gli spazi non consecutivi, inserendo inoltre le eccezioni che servono (tipo presenza di trattini).

C_LONGINT($numeroparole;$posizione)
C_TEXT($1)

$numeroparole:=0
If (Length($1)>0)
      For ($posizione;1;(Length($1)-1))
          If (($1[[$posizione]]=Char(32)) & ($1[[$posizione+1]]#Char(32)) & ($1[[$posizione+1]]#"-"))
           $numeroparole:=$numeroparole+1
          End if
      End for
      $numeroparole:=$numeroparole+1
End if
$0:=$numeroparole


2
Info Info Impedire la connessione ODBC
Se si vuole impedire l'accesso via ODBC ad un particolare database 4th Dimension, ad esempio perché ci sono più server attivi, ma solo alcuni devono essere visibili via ODBC, è possibile negare questo tipo di connessione.

Per fare ciò bisogna deselezionare la voce "Allow 4D Open Connections" nelle database properties in questo modo:
- aprire il database via 4D Client;
- da Design aprire le proprietà del database;
- nella pagina "Data control and access" deselezionare "Allow 4D Open connection".

La modifica avrà effetto a partire dal successivo riavvio di 4D Server.


1
Bug Bug [Risolto] Installer 2004.3 dopo l'installazione della 2004.1
Grazie ad una news pubblicata da 4DToday qualche settimana fa, ho potuto installare 4D 2004.3 su una macchina dove erano stati installati tutti i 4D 2004 precedenti (compresa la versione 2004.1), risolvendo un problema legato a InstallShield. All'inizio dell'installazione della 2004.3, infatti, l'installer segnala un errore 6001.
Per risolvere "manualmente" questo problema è sufficiente rimuovere la DLL nel percorso:

C:\Programmi\File comuni\InstallShield\Professional\RunTime\0701\Intel32\setup.dll

La cartella potrebbe essere nascosta, e quindi accessibile solo o digitandone il percorso o facendo visualizzare al sistema anche cartelle e file nascosti.



3
Comandi Comandi Esportare dati con EXPORT TEXT *
Il comandi EXPORT TEXT ({table; }document) permette di esportare dati da una tabella a partire dalla selezione corrente (basta dunque eseguire precedentemente una query per esportare solo ciò che serve). L'esportazione viene eseguita utilizzando l'OUTPUT FORM e i campi vengono inseriti nell'ordine in cui si trovano nel form. Gli oggetti non campi (tipo i pulsanti) non vengono considerati.
Per ogni record esportato viene generato un evento On Load: così è possibile esportare anche variabili, impostandone i valori in questo evento.

Il nome del documento può essere quello di un documento nuovo o esistente. Se già presente, il documento viene automaticamente sovrascritto senza preavviso (se si vuole evitare ciò è bene usare prima il comando Test path name sul nome del documento da creare).

Se si passa una stringa vuota come nome del documento viene visualizzata la finestra standard di salvataggio file: se si preme Salva la variabile di sistema OK prende il valore 1.

Di default, il delimitatore di campo è la tabulazione (ASCII 9 o Tab) e quello dei record il return (ASCII 13 o CR). E' comunque possibile modificarli cambiando i valori (numerici) delle variabili FldDelimit e RecDelimit.



2
Tecniche Tecniche Deselezionare gli elementi di una listbox **
Le list box "ricordano" la riga selezionata, il che significa che visualizzando uan listbox già visualizzata potremmo trovare una riga già selezionata.
Per evitare ciò, se arrEsempio è uno degli array usati dalla listbox ListBox, basta scrivere:

SELECT LISTBOX ROW (ListBox; Size of array(arrEsempio)+1)



7
Tecniche Tecniche Metodo di indirizzamento delle stampe [1]

Sottotitolo: [Bug] [Risolto] 2003.6 e 2003.7 OSX 10.3 e 10.4 non imposta la stampante richiesta, non preleva correttamente la carta

Ho finalmente avuto il tempo di affrontare questo argomento che nel mio ambiente di lavoro mi creava problemi da quando sono passato alla v 2003.
Qui da noi ogni giorno 10 client stampano parecchio materiale, saltando dalle etichette adesive da prelevare dai vassoi, al fogli standard nei cassetti, ai cartellini a colori per il self-service, alle etichette sempre a colori dei prodotti, utilizzando 3 stampati di rete postscript in TCP/IP, alcune stampanti inkjet USB e una Inkjet A3 condivisa. Tutti gli utenti erano costretti a impostare manualmente tutti i parametri per ogni stampa eseguita.

Ho esaminato le informazioni che mi è stato possibile trovare in ambito internazionale, sia note tecniche sia messaggi postati ai diversi NUG, testando le soluzioni proposte (alcune delle quali abbastanza astruse, come quella di creare diverse copie dei documenti PPD e di rinominarli al volo da method per costringere l’OS ad usare la configurazione voluta...).

Ho trovato una soluzione che finalmente funziona bene e che utilizza i comandi standard, soluzione basata sulle funzioni di salvataggio e recupero dei parametri di stampa in BLOB fornite dal plug-in ACI_Pack. Ciò implica il salvataggio del setup in una table ma a mio parere ne vale la pena. La soluzione è testata con tutte le funzioni di stampa, compresa PRINT FORM, ma non con i QuickReport che non uso.

Creazione e salvataggio impostazioni di stampa, è importante la corretta successione dei comandi:

1) eventuale impostazione del formato con PAGE SETUP, se necessario;
2) ottenimento di tutti i parametri di stampa con PRINT SETTINGS;
      istruendo l’utente a impostare tutti i parametri con attenzione, anche il numero delle copie
3) trasferimento del setup in una variabile BLOB con AP Print settings to BLOB;
4) salvataggio del nome della stampante selezionata;
5) salvataggio del BLOB con i parametri.

Esempio, assumendo di avere creato una table [ParametersTable] dove registrare i parametri di stampa

C_BLOB($mioBlob)
PAGE SETUP ([myTable];"PageSetupForm")
PRINT SETTINGS
If (OK=1)
    $error:=AP Print settings to BLOB ($mioBlob)
    If ($error#1)
           ALERT ("Errore generando il BLOB dei Parametri di stampa.")
    Else
           CREATE RECORD ([ParametersTable])
           [ParametersTable]PrinterName:=Get current printer
           [ParametersTable]ParametersBLOB:=$mioBlob
           SAVE RECORD ([ParametersTable])
    End if
End if

Nota: è indispensabile trasferire i parametri in una variabile BLOB e poi assegnarla al campo BLOB, non usare la funzione AP Print settings to BLOB con un campo quale argomento della funzione perché poi il BLOB può generare errori.



1
Tecniche Tecniche Eseguire più 4DServer sulla stessa macchina *
È possibile far girare più di una applicazione 4DServer sulla stessa macchina. L'unico accorgimento che bisogna prendere è quello di "customizzare" ognuna delle sessioni.
4DServer pubblica i database sempre sulla stessa porta TCP/IP, e risulta dunque necessario modificare questo parametro per ognuno dei server da attivare.
La procedura da seguire inizia con l'individuazione del file tcp.opt nel cartella di sistema 4D; copiare questo file in ognuna delle cartelle dei 4DServer che vogliamo attivare; aprire ognuno dei file (al limite tranne uno, il 19813 standard) col Customizer e modificare il valore della porta con un numero vicino a quello visualizzato e comunque diverso da ognuno degli altri numeri assegnati.
A questo punto, lanciando 4DClient, basterà inserire come indirizzo del server xxx.zzz.yyy.aaa virgola numero della porta assegnata in precedenza.

2
Tecniche Tecniche Spostare o copiare una cartella
Come chiesto da Michele Bertoli sul forum 4th Dimension non esiste in maniera nativa un comando 4D che permetta di copiare o spostare una cartella.
Le possibilità a questo punto sono
- creare la cartella (se serve) con CREATE FOLDER e usare un ciclo di MOVE DOCUMENT o COPY DOCUMENT per spostare i file
- usare un file batch che esegua lo spostamento via linea comando, ad esempio:

SET ENVIRONMENT VARIABLE("_4D_OPTION_HIDE_CONSOLE";"true")
LAUNCH EXTERNAL PROCESS("mycommand.bat")




1
Bug Bug [risolto] 4D Engine 2003.7 con Mac OS 10.4.4
Ho aggiornato il sistema operativo del Mac dal 10.3.9 al 10.4.4 e mi sono accorto che non è più possibile creare una applicazione inserendo il 4D Engine versione 2003.7 (resta in grigio chiaro e quindi non selezionabile). Testato il problema su altre tre macchine semore Mac con system 10.4.4 o 10.4.3 identico problema.
Unica soluzione trovata: riformattare la macchina e tornare al 10.3.9 sigh..! :(


2
Tecniche Tecniche Merge di due file dati
Franz chiede:
Qualche esperto mi saprebbe dire come unire due files di dati in un unico file (subrecords compresi) in modo da avere un unico archivio dati ? Grazie !

Risposta:
Usando le due procedure dalla Faq Rapido Trasferimento Dati l'operazione è molto semplice, posto di avere due base dati con la stessa struttura.

Quindi, abbiamo le due base dati A e B e vogliamo trasferire tutto da B accodandolo ad A, incluso di subfile, immagini e Blob.

1. Inseriamo nella struttura le due procedure, DB_Esporta e DB_Importa
2. Teniamo la stessa struttura e le due base dati nella stessa cartella
3. Apri la base dati B ed eseguiamo DB_Esporta (crea vari file di passaggio)
4. Apri la base dati A ed esegui DB_Importa (trova i file e li legge)

1
Plugin Plugin 4D Open e i Network Component
Dalla versione di 4D 2003, i componenti non-TCP/IP non sono più usati, per cui il comando OP Load Network Component è obsoleto.

L'ID del TCP/IP è 29 su Mac OS e 2 su Windows. Quindi quando viene richiesto un componente in un comando di 4D, bisogna usare direttamente la costante, come nell'esempio:

PLATFORM PROPERTIES($sistema_l)
If($sistema_l<3)
  netCompID:=29 `sono su Mac
Else
  netCompID:=2 `sono su Windows
End if
$error:=OP Select 4D Server (netCompID;$NomeServer;$IDServer;True)

1
Tecniche Tecniche Scelta della chiave primaria
Un punto critico nell'ideare lo schema concettuale di un database è la scelta degli attributi caratteristici dei set di entità che sono in definitiva le tabelle. Un attributo o un insieme di attributi i cui valori identifichino in modo univoco ogni entità del set (record) è chiamato chiave.

In linea di principio ogni tabella dovrebbe avere una chiave, in modo che ogni record sia distinguibile dall'altro.

Anche se il mondo reale offre a volte delle chiavi naturali, in molti casi è preferibile usare un dato a parte che non possa cambiare per nessun motivo: i programmatori 4D hanno a disposizione per tale fine la funzione Sequence number che genera un numero univoco per ogni record creato per ogni tabella.

D'altro canto l'uso di Sequence number ha degli svantaggi da considerare,
dovuti proprio alla propria unicità e al legame diretto con la struttura.
Per esempio:
- in caso di danneggiamento del file dati, quando l'unica soluzione è
esportare i dati e ricrearli in un nuovo file;
- in caso di esportazione/importazione di dati per il passaggio ad una
nuova versione (vedi la faq Rapido Trasferimento Dati);
- unione dei dati provenienti da strutture distinte, anche se uguali.

Per ovviare a questi inconvenienti è meglio usare dei contatori creati in
proprio. Ecco un esempio in cui la tabella [MieiContatori] ha un campo per
ogni contatore che voglio tenere:

C_POINTER($1;$PuntaAlCampo)
C_LONGINT($0)

$PuntaAlCampo:= $1

READ WRITE([MieiContatori])

If (Records in table([MieiContatori])=0)
        CREATE RECORD([MieiContatori])
        SAVE RECORD([MieiContatori])
End if

ALL RECORDS([MieiContatori])

While (Locked([MieiContatori])) ` controllo se è bloccato
        DELAY PROCESS(Current process;10)
        LOAD RECORD([MieiContatori])
End while

$PuntaAlCampo-> := $PuntaAlCampo->+1
$0 := $PuntaAlCampo->
SAVE RECORD([MieiContatori])
UNLOAD RECORD([MieiContatori])
READ ONLY([MieiContatori])


2
Codice Codice Calcolo del checksum di un codice a barre EAN13 *
EAN13 è uno dei tipi di barcode più usati (il suo equivalente negli Stati Uniti è il codice UPC-A,che è un sottoinsieme di EAN13, ma dal 2005 i negozi americani devono accettare anche EAN13, eliminando di fatto la differenziazione).
Il tredicesimo carattere di un codice EAN13 è il codice di controllo del codice a barre, che viene calcolato utilizzando questo sistema:
- Si sommano le cifre del codice di posto pari
- Si aggiunge la somma delle cifre di posto dispari, ma moltiplicata per tre.
- Il checksum sarà il numero da aggiungere a questa somma per ottenere il primo multiplo di 10 immediatamente superiore.

Esprimiamo l'algoritmo di formato 4th Dimension:

$check:=0
For ($i;12;1;-1)
      If (($i/2)#($i\2))
           $check:=$check+(Num($String_to_encode[[$i]]))
      Else
           $check:=$check+(Num($String_to_encode[[$i]])*3)
      End if
End for

$check_S:=String($check)
$check:=10-Num(Substring($check_s;Length($check_s)))


Fonte: 4D Knowledgebase


2
Tecniche Tecniche Teoria della normalizzazione: dipendenze funzionali *
Cos’è una dipendenza funzionale? Analizziamo il seguente esempio:

[CAP]
CAP
Città
Provincia
Abbreviazione_nome_regione
Nome_Regione

Il CAP è un codice univoco di 5 caratteri. Cosa lo rende una chiave? Il fatto che esso determina tutti gli altri campi. Poiché per ogni CAP esistono una singola Città, una singola Provincia, ecc., questi campi sono in dipendenza funzionale rispetto al campo CAP.

Osserviamo poi gli ultimi due campi: l’Abbreviazione determina esattamente la Regione, cioè la regione è in dipendenza funzionale rispetto all’Abbreviazione, che ne fa dunque le veci di una chiave. Ma allora, se Abbreviazione_nome_regione è una chiave, questo campo deve appartenere ad un’altra tabella.

Ecco, la Terza Forma Normale (3NF) ci dice proprio che dobbiamo allora creare una tabella [Regioni] che avrà come campi Abbreviazione_nome_regione (chiave primaria) e Nome_Regione

Consulta da questo link l’indice delle faq sulla normalizzazione

2
Tecniche Tecniche Creare un'immagine lampeggiante *
Per creare un immagine lampeggiante in una maschera, segui questi passi::
1. Crea un nuova aimmagine nella Picture library.
2. Imposta l'immagine a 2 colonne e 1 riga
3. Incolla l'immagine nel secondo frame, lasciando il primo vuoto.
4. Trascina l'immagine così creata su un form per craere un picture button, chiamato ad esempio PulsanteImmagine.
5. Aggiungi il seguente codice nel metodo del form:
If (Form event=On Load)
  Set Timer(tickCount) `60esimi di secondo, da impostare secondo la velocità desiderata
End if
If (Form event=On Timer )
  If (PulsanteImmagine=0)
    PulsanteImmagine:=PulsanteImmagine +1
  Else
    PulsanteImmagine:= PulsanteImmagine -1
  End if
End if


1
Tecniche Tecniche Teoria della normalizzazione: la chiave primaria
Il concetto di “primary key” è fondamentale nella teoria dei database. Il concetto è semplice: ogni record deve avere qualcosa che lo identifichi univocamente.

La chiave primaria di una tabella serve inoltre come punto di partenza per la gestione delle relazioni con le altre tabelle: per esempio una fattura è un relazione con un unico e ben determinato cliente, come un impiegato è assegnato ad un unico e ben determinato ufficio.

Una chiave primaria deve avere un valore per ogni record.

La chiave primaria può essere formata da un campo o dalla combinazione di più campi. Questo dato dei database relazionali ha bisogno di una discussione a parte per quanto riguarda 4th Dimension: se molti sistemi di sviluppo per database usano esplicitamente il concetto di chiave primaria formata da più campi, ciò non avviene in 4D. In realtà è quasi banale bypassare questo limite aggiungendo alla tabella un campo che memorizzi la concatenazione dei campi che compongono la chiave primaria. Una chiave del genere può essere molto facilmente gestita utilizzando i trigger.

Una chiave primaria deve essere unica, obbligatoria e immodificabile: un classico errore è quello di attribuire il valore di chiave primaria a campi “volatili”. Ad esempio, per la tabella:

[Clienti]
Nome
Indirizzo

il campo Nome sembrerebbe un buon candidato come chiave primaria: sbagliato! Cosa succede se Nome cambia, ad esempio per correggere un semplice errore di inserimento? Dovremo cambiare tutti i record delle fatture di quel cliente.
Risulta molto più corretto usare un valore “esterno” ai dati reali, come Sequence number, o qualsiasi altro sistema che generi comunque dei valori da chiave primaria.

Per completezza sull’argomento diamo anche la definizione di superchiave, che non è altro che un insieme di campi per i quali la tabella non contiene due record con valori identici per tali campi (non è altro che il superinsieme di una chiave).
Inoltre in uno schema relazionale possono esserci più chiavi (ma solo una di esse verrà definita “principale”).

Consulta da questo link l’indice delle faq sulla normalizzazione

1
Comandi Comandi Come usare il Sequence Number
La funzione Sequence Number ritorna un numero progressivo automatico per ogni tabella ed è usato per creare il codice identificativo (o chiave primaria) del singolo record. Parte da 1 alla creazione del database ed è incrementata da 1 per ogni record salvato.

La funzione però aveva alcuni limiti per cui era sconsigliata: in pratica poiché non era possibile modificarne il valore corrente diventava difficile, ad esempio, spostare i dati da un database all'altro o ripartire da un certo numero.

Finalmente dalla 2004.1 è disponibile un modo accedere al valore usato dal Sequence Number:

1. Get Database Parameter ( Tabella ; Table Sequence Number ) -> Longint
Legge il valore corrente del prossimo numero che sarà assegnato dalla Sequence Number per la Tabella passata come primo parametro

2. SET DATABASE PARAMETER ( Tabella ; Table Sequence Number ; Longint )
Imposta il prossimo numero progressivo che sarà generato dalla Sequence Number pe la Tabella.


1
Info Info 4th Dimension e Mac OS 10.4 - Tiger *
La prima versione di 4D di comprovata compatibilità col nuovo sistema operativo di casa Apple, Tiger, sarà la 2004.2.

Per quel che riguarda le altre versioni al momento non si hanno notizie ulteriori.



1
Comandi Comandi SET TABLE TITLES e SET FIELD TITLES *
Il comando SET TABLE TITLES permette di nascondere, riordinare o rinominare le tabelle presenti nel database quando questo elenco appare nelle dialog di 4th Dimension, come ad esempio il Query Editor o Quick Report.

La sintassi è:

SET TABLE TITLES (tableTitles; tableNumbers)

dove tableTitles è l'array contenente i nuovi nomi e tableNumbers le attuali posizioni nella struttura (table number).

Gli array devono essere sincronizzati. Per non far comparire una tabella basta non includerne titolo e numero negli array.

Quindi, ad esempio supponiamo di avere tre tabelle A, B e C, create in questo ordine, e di volerle far apparire come X, Y e Z. Inoltre non vogliamo che la tabella B sia visibile. Infine, vogliamo far apparire le tabelle nell'ordine Z e X. Tutto ciò si fa semplicemente inserendo Z e X nell'array dei nomi e 3 e 1 nell'array delle posizioni.

SET TABLE TITLES non modifica la struttura, ma è valido per le semplici sessioni: quindi ad esempio, più 4D Client possono vedere lo stesso database simultaneamente in modo differente.

SET TABLE TITLES non ha il potere di modificare l'attributo Invisible attribuito ad una tabella nella struttura: così, una tabella invisibile continuerà ad esserlo, anche se inserita negli array passsati al comando.

Il comando SET FIELD TITLES è molto simile, semplicemente applica le stesse considerazioni di SET TABLE TITLES ai campi di una tabella.


2
Plugin Plugin QPix: un'introduzione *
Ci sono fondamentalmente due possibilità per gestire le immagini in 4D. La
prima è quella di usare i comandi del linguaggio standard, la seconda di
usare un plug-in esterno. QPix è il plug-in della Escape per il trattamento delle immagini nei database 4th
Dimension.
Utilizzando la tecnologia di QuickTime, QPix permette, ad esempio:
- di acquisire informazioni su un'immagine;
- caricarla da un file per visualizzarla in un'area QPix oppure in una
variabile o in un campo;
- filtrarla e comprimerla;
- crearne una thumbnail di qualità normale o alta;
- acquisirla da una fonte TWAIN, creando volendo anche dei TIFF multipagina;
- esportarla su file in uno dei formati supportati da QuickTime.

1
Plugin Plugin Backup di 4d Monoutenza *
4dBackup è un plugin forinito con 4d che di solito si usa in versione client-server. E' possibile però usarlo anche in monoutenza, ma o lo si esegue in ambiente User o occorre comandarlo da procedura. Ecco un esempio di utilizzo:

C_INTEGER ($Progress_i;$Fill_i)
If (BK Begin full backup = 0)
      If (BK Start copy = 0)
           Repeat
              BK GET PROGRESS ($Progress_i; $Fill_i)
              MESSAGE ("Backup in corso: " + String ($Progress_i) + "%")
           Until (BK Get state # 4)
      End if
      BK END BACKUP
End if


1
Info Info Le icone identificative dei campi
Le icone che si trovano accanto ai campi delle tabelle nella Structure window sono rintracciabili usando i numeri di pict a partire da 150, ad esempio:

- 150 restituisce l'icona del campo di tipo string;
- 151 restituisce l'icona del campo di tipo real;
- 152 restituisce l'icona del campo di tipo text;
- 158 restituisce l'icona del campo di tipo int;
- 159 restituisce l'icona del campo di tipo longint.


1
Macro Macro Metodo dei pulsanti *
Scrivendo un metodo per gli oggetti è possibile selezionare gli eventi nelle proprietà e scrivere il codice per gestire solo un particolare evento. Questo purtroppo non è molto leggibile, perche, ad esempio, in fase di debug potresti non sapere se e quale evento è selezionato quando tracci il codice.

E' quindi buona norma gestire gli eventi con il solito Case, anche per gestire il clic su un pulsante, che è l'evento più normale.
Per facilitare il compito di scrivere sempre la stessa cosa, ecco una macro che lo fa per conto nostro.



Case of
:(Form event=On clicked)

End case



Basta incollare questo codice XML nel file Macros.xml file, che si trova nella corrente cartella 4D di sistema, all'interno dei tag .

A questo punto è possibile usare all'interno del metodo la macro usando il menu contestuale (click-destro su windows o control-click su mac) e scegliendo la macro "OnClicked" dal menu "Insert Macro"

1
Info Info Personalizzazione del Database Structure *
E' possibile modificare lo sfondo standard della finestra del database structure con una
immagine personalizzata.

IMPORTANTE: LA MODIFICA E' DEFINITIVA, nel senso
che non è possibile ritornare all'immagine di sfondo standard di 4D (quella
con gli ingranaggi, per intenderci).
Per effettuare la modifica:
- mettere negli appunti l'immagine che si vuole come sfondo;
- cliccare su un punto vuoto (senza tabelle o relazioni) della finestra
Database structure;
- incollare l'immagine.

1
Novizi Novizi Jumpstart 4D: ovvero un manuale completo di 4th Dimension
Uno degli aspetti più difficoltosi in cui un utente si imbatte iniziando a programmare con 4D è la vastità di informazioni dove attingere, dove per informazioni intendiamo ovviamente i manuali. Da quale parto? Cosa mi serve? E se non trovo ciò che mi serve?
Se le varie faq di introduzione a 4D sono troppo piccole, o se gli articoli di 4D sul passaggio da FileMaker Pro a 4th Dimension non vi hanno risolto il problema, un'altra strada da seguire potrebbe essere Jumpstart 4D, il manuale scritto da Steve Hussey che porta il programmatore ad avere una conoscenza di base ma completa del prodotto, partendo dalla struttura, passando poi agli ambienti User e Custom, password, compilazione e distribuzione del prodotto. Il tutto aiutato dalla costruzione guidata di un piccolo database di gestione fatture.

Le informazioni potete trovarle su 4D Press.
Jumpstart 4D è acquistabile per $29 in versione cartacea su Amazon o su 4D Store, oppure si può scaricare gratuitamente il PDF dal sito ftp di 4d.



1
Comandi Comandi Il comando Get indexed string
Utilizzando una sintassi del tipo:

Get indexed string (resID; strID{; resFile})

dove:

- resID è il numero della risorsa;
- strID è il numero della stringa;
- resFile è il numero identificativo del resource file da usare, altrimenti, se omesso, tutti i file aperti;

il comando permette di ottenere la stringa contenuta nella risorsa lista di stringhe resID in posizione strID. Per ottenere tutte le stringhe di una risorsa di questo tipo si usa invece il comando STRING LIST TO ARRAY.


1
Novizi Novizi Prima introduzione a 4d: FILE E CAMPI *
Prima cosa creare file e campi, nella terminologia di 4D si usano i termini
inglesi Table(s) e Field(s). E qui non ci sono problemi, i campi hanno il
loro type (tipo, cioe' se alfa, numerico, ecc.) che e' autoesplicativo. Non
esistono campi "calcolati" perche' in 4D ci sono funzioni molto piu' potenti
che vedremo in seguito.
L'unica nota particolare e' che Tables e Fields non si possono piu'
cancellare. Se crei un Table (un file) che poi non ti serve lo lasci dove si
trova e basta, semmai lo utilizzerai in seguito se servira'; se non aggiungi
records non occupa nemmeno memoria dati. Se in un Table crei un campo che
non ti serve, e' bene usare qualche accortezza per evitare di trovarselo tra
i piedi: primo dagli un nome che ricordi che e' inutile (per esempio
"spurio") poi impostalo come invisibile cosi' non compare inutilmente in
giro e poi imposta il type come booleano che e' il type che occupa meno
memoria (in RAM e su disco).
Nota che i nomi di Tables e Fields si possono cambiare quando si vuole.

1
Codice Codice Riconoscere un anno bisestile *
Ecco un piccolo frammento di codice che prende in input un numero e restituisce True se l'anno rappresentato dal numero è bisestile:

C_BOOLEAN($0)
C_LONGINT($1;$anno_l)
$anno_l:=$1
$0:=True
Case of
    : (Dec($anno_l/400)=0)
        `è bisestile, come il 2000
    : (Dec($anno_l/100)=0)
        `non è bisestile, come il 1900
        $0:=False
    : (Dec($anno_l/4)=0)
        `è un anno bisestile
    Else
        $0:=False
End case


1
Codice Codice Calcolo del numero della settimana *
Seguendo le regole dell'Iso 8601:
- il primo giorno della settimana è Lunedì
- una settimana è contata nell’anno in cui stanno la maggior parte dei giorni
- E’ possibile avere anche anni con 53 settimane

Propongo una soluzione, da testare:

$d:=Date("04-01-"+String(Year of(Current date)))
$0:=Int((Current date-(1+$d-Day number($d)+(7*Num(Day number($d)>4))))/7)+1

Si sarebbe potuto scrivere su più righe per essere più chiari, o in una riga sola per essere più concisi...

1
Info Info Help in linea di 4D [4] : 4D Help Html
Un Help in linea molto completo è quello in versione HTML consultabile con un browser. Questo tipo di Help si richiama premendo il tasto funzione F1 dopo aver selezionato un comando 4D (su Windows non dovrete aver installato 4d.HLP). Viene aperto il vostro browser e mostrata una pagina con la sintassi e tutte le informazioni utili sul comando scelto.
Da questa finestra utilizzando i vari link è possibile consultare tutti i comandi di 4D, in pratica il Language Reference, e tutte informazioni di maggior utilità sui vari programmi e Plugin che fanno parte delle soluzioni 4th Dimension.

Tutto ciò è contenuto nella cartella Documentation (di 54,9 Mb): i file si possono scaricare dall' ftp di 4D.com (versione Macintosh o Windows) oppure copiare dal CD di installazione.

Copiata la cartella sul disco (magari nella stessa folder dove avete messo l'applicativo), per poter richiamare in maniera veloce questo Help come sopra spiegato bisogna specificare a 4D dove si trovano i documenti HTML dal menu:

  4th Dimension | Preferences | Design mode | Documentation

qui scegliere Local folder e sfogliare il percorso fino alla vostra cartella Documentation.


1
Tecniche Tecniche Mettere una formula nel subtotal di Quick Report *
Anticipo che il titolo non è proprio veritiero, nel senso che quanto scritto è possibile solo passando poi da excel.

L'esempio è avere un report che riporti le vendite di quest'anno paragonate alle vendite dell'anno passato calcolando il delta.
Nel nostro report avremo una colonna con le vendite1 una colonna con le vendite 2 e una colonna calcolata 100-(vendite1*100)/vendite2).
Se volessimo avere un break per regione non esiste sistema per poter calcolare il delta nel subtotal.

Il sistema che ho trovato si basa sul fatto che se scriviamo nel subtotal all'interno della cella della terza colonna una formula che non sia una delle sue, quick report riporta pari pari la scritta.

In excel esiste la funzione "R1C1 reference style" che deve essere settata, fatto questo nella nostra cella possiamo mettere "=100-((RC1*100)/RC2)" senza apici.

Se questo report lo esportiamo come HTML e lo apriamo con Excel avrete il risultato anche nel subtotal. Uso html per il mantenimento della grafica.



1
Tecniche Tecniche Cambiare dinamicamente gli Help Messages *
Forse non tutti sanno che è possibile modificare il contenuto degli Help Messages (le micro finestre gialle che forniscono info sugli oggetti dei forms posizionando il cursore su di essi) in modo dinamico e sensibile al contenuto o al contesto.

Basta applicare la già nota tecnica illustrata nell'articolo "Displaying variables and field values in Text objects" presente nell'elenco 4D Tech Tips della home:

- dedicare una variabile Text a questo scopo, per esempio vTxt_OKbuttonHelp
- nella finestra di definizione dell'oggetto aprire il tab all'ultima posizione dove si impostano gli help messages
- nel campo "Help message" inserire in nome della nostra variabile tra i caratteri "<" e ">" così < vTxt_OKbuttonHelp >

l'help mostrerà ora il contenuto della variabile che può essere definito da codice, per esempio:

If (MyField # "")
    ENABLE BUTTON(vBt_OK)
    vTxt_OKbuttonHelp:="Conferma la scheda e registra le modifiche"
Else
    DISABLE BUTTON(vBt_OK)
    vTxt_OKbuttonHelp:="Conferma la scheda, non attivo perchè mancano dei dati"
End if

1
Codice Codice Chiudere i processi correttamente uscendo da 4D *
Il metodo On Exit Database viene eseguito all'uscita del database. Questo metodo viene eseguito da 4D quando viene eseguita un'istruzione QUIT 4D o quando viene scelta la voce di chiusura applicazione da menu. Se il metodo On Exit Database è vuoto, l'applicazione verrà chiusa immediatamente (senza tenere conto quindi delle operazioni attualmente in esecuzione), altrimenti, se contiene del codice, 4D attende per chiudersi che il metodo venga portato a termine: possiamo sfruttare questa attesa per far sì che i processi attivi vengano chiusi con cognizione.

Intanto, all'apertura del database impostare la variabile booleana <>StoChiudendo_b impostandola a False. A questo punto nell'On Exit Database la impostiamo a True e "risvegliamo" ogni processo:


<>StoChiudendo_b:=True
For ($i;1;Count tasks)
    RESUME PROCESS($i)
    CALL PROCESS($i)
End for


Così facendo il programma sa che 4D sta per chiudersi: ragion per cui si dovrebbe programmare ogni metodo che usa dei cicli e che vogliamo sia chiuso correttamente in maniera tale da controllare lo stato di "chiusura" di 4D guardando il valore della variabile <>StoChiudendo_b.

Per quel che riguarda invece i metodi dei form, visto come abbiamo scritto il metodo di chiusura, viene generato un evento On Outside Call che possiamo gestire:

Case of
    : (Form event=On Outside Call)
      If (<>StoChiudendo_b)
           CANCEL ` o qualsiasi altra istruzione sia necessaria
      End if
End case



1
Codice Codice Aumentare la casualità del comando Random
Il comando Random restituisce un un numero a caso tra 0 e 32.767.
Può capitare che il numero casuale che cerchiamo sia oltre questo limite.
Inoltre il tipico uso che viene fatto del comando è quello di restituire un numero compreso in un certo intervallo.
Ecco quindi un semplice metodo per aumentare le potenzialità del comando Random:

C_LONGINT($minimo_l;$massimo_l;$1;$2)
$minimo_l:=$1
$massimo_l:=$2

C_LONGINT($aCaso_l;$0)
If ($minimo_l=$massimo_l)
    $aCaso_l:=(Random*Random)
Else
    $aCaso_l:=((Random*Random)%($massimo_l-$minimo_l+1))+$minimo_l
End if

$0:=$aCaso_l

1
Web Web Servire le pagine web inesistenti con 4D
La parte web di 4D permette di servire o pagine fisiche o pagine generate da codice. Se non è possibile soddisfare la richiesta, 4D invia un mesaggio standard di pagina non trovata al browser.
È però possibile modificare questa pagina aggiungendo una risorsa alla struttura nella maniera che segue:
- aprire 4D su Mac con un editor di risorse;
- copiare la risorsa Html numero 45 nella struttura;
- copiare il contenuto della risorsa in un editor html o un editor di testo per effettuare le modifiche;
- copiare di nuovo l'HTML modificato nella risorsa.

A questo punto la pagina servita per le pagine non trovate sarà quella da noi modificata.

1
Info Info Help in linea di 4D [1] : Explorer Help *
All'interno della finestra di method editor, dopo aver terminato di scrivere un comando di 4D, l' Explorer Help visualizza la sintassi del comando nella parte alta della finestra.
Perché questo funzioni deve essere installato un file, che fornisce le informazioni di aiuto, il suo nome è "4D Help" su Macintosh e "4D Help.RSR" su Windows.
Questo file di help non va confuso con il Menu di Help, che utilizza un altro file chiamato 4D.HLP.

"4D Help" per l'Explorer Help può essere comodamente scaricato dal sito ftp di 4D.com da questo indirizzo ed installato nella seguente cartella di sistema:

Macintosh = Library:Application Support:4D
Windows = C:\Document and Settings\All Users\Application Data\4D

Dopo l'installazione l'Explorer Help è fruibile su quel computer sia se utilizzate un 4D Client oppure una versione Desktop.

1
Info Info 4th Dimension, MS Access e FileMaker Pro [5] Inserimento nei campi **
Controllo dell'inserimento nei campi

I filtri di inserimento controllano i caratteri che è consentito digitare in un campo (o in una variabile) da parte dell'utente.

Per esempio se voglio controllare l'inserimento di un codice fiscale posso mettere un filtro del tipo "˜A######&9##˜A#&9##˜A#&9###˜A#".
Dei tre sistemi solo Access e 4D possiedono questa caratteristica, non FileMaker.

Inoltre in FileMaker non è possibile controllare un evento del tipo "on data change" che permetta di eseguire del codice all'uscita da un campo a controllare i dati appena inseriti o modificati.

Consulta da questo link l’indice delle faq su 4th Dimension, MS Access e FileMaker Pro

2
Info Info 4th Dimension, MS Access e FileMaker Pro [4] La sicurezza *
La sicurezza

Sul versante sicurezza i tre sistemi risultano abbastanza differenti.
In FileMakerPro non esiste una combinazione utente - password come gli altri sistemi, ma supporta solo password. Inoltre le password sono definite a livello dei file, il che significa che per cambiare una password è necessario aprire tutte le tabelle.

Il modello di sicurezza di Access è abbastanza flessibile: possono essere definiti utenti, gruppi di utenti, e i privilegi possono essere assegnati ai singoli utenti o ai gruppi.

Anche 4D permette la creazione di utenti con password e gruppi di utenti e la gestione dei privilegi. Una differenza assai significativa sta nella possibilità di usare una protezione SSL nella comunicazione tra 4D Server e 4D Client: ciò comporta ovviamente una maggiore sicurezza delle comunicazioni, impedendo di fatto un loro intercettamento e/o alterazione.

Consulta da questo link l’indice delle faq su 4th Dimension, MS Access e FileMaker Pro

1
Info Info 4th Dimension, MS Access e FileMaker Pro [3] I form *
I form

Se da un lato tutti e tre i prodotti consentono una facile creazione di un form grazie ai wizard, d'altro canto il tipo di oggetti e la possibilità di personalizzarli risulta ben differente.

4D, ad esempio, possiede oggetti per i form che non sono presenti in Access o in FileMaker, come popup menu grafici o gerarchici, liste gerarchiche, splitter, matrici di pulsanti. FileMaker non possiede inoltre i Tab Control, utili ad esempio per gestire form multipagina.

FileMaker Pro 7 ha finalmente apportato delle cospicue migliorie nella personalizzazione dei form: a differenza delle versioni precedenti, infatti, risulta possibile indicare dimensione e coordinate delle finestre, nonché aprire più fineste della stessa tabella contemporaneamente, ognuna con una selezione differente. Continuano però a mancare, ad esempio, i tips al passaggio del mouse su un pulsante.

In Access, a differenza di 4D o FileMaker, un form non appartiene ad una tabella specifica: ciò significa che il form non sa, in partenza, quale è l'origine da cui prendere i dati.

4th Dimension permette una notevole personalizzazione dell'interfaccia, ad esempio:
- controllo su posizione, tipo e dimensione delle finestre;
- più form per la stessa tabella aperti contemporaneamente;
- visibilità controllabile degli oggetti;
- form multipagina;
- tips su tutti gli oggetti del form;
- stili personalizzati che controllano l'aspetto dell'applicazione a seconda del sistema operativo usato, e non solo windows-mac ma anche per le diverse versioni sulla stessa piattaforma;
- personalizzazione della corrispondenza fra combinazioni su tastiera e voci di menu, pulsanti, azioni.

Consulta da questo link l’indice delle faq su 4th Dimension, MS Access e FileMaker Pro

1
Info Info 4th Dimension, MS Access e FileMaker Pro [2] Creazione della struttura *
Creazione della struttura
Il primo passo passo da compiere nella progettazione di un database è la creazione della struttura, intesa come definizione di tabelle, campi e relazioni.

In Access la struttura viene creata attraverso un'interfaccia tipo foglio di calcolo, in cui ogni riga rappresenta un campo (colonna) della tabella. Per ogni campo possono essere definiti molti attributi. La definizione delle relazioni dovrà essere impostata in una finestra a parte.

Anche in FileMaker definizione della struttura e definizione delle relazioni avvengono in finestre separate: con la versione 7 è stato abbandonato il sistema ad elenco per passare ad una più moderna ed intuitiva visualizzazione grafica (nonché simile a quella degli altri due sistemi). Rispetto ad Access (e anche a 4D), FileMaker introduce un nuovo tipo di campo, il "campo calcolato", croce e delizia dei programmatori FMP. I campi calcolati vengono definiti usando un editor specifico e vengono trattati alla stessa stregua dei campi "standard": FileMaker si occupa di effettuare il calcolo quando ritiene necessario; se da un lato questo tipo di approccio può sembrare conveniente, esso in realtà nasconde dei problemi. Intanto, visto che il programmatore non ha controllo sull'esecuzione dei calcoli, le prestazioni possono abbassarsi irrimediabilmente. Inoltre, malgrado la versione 7 permetta di creare un file di dati separato dal file contenente script e layout, non risulta un'operazione semplice trasferire nel file della struttura i campi calcolati.

In 4th Dimension la creazione di tabelle, campi e relazioni avviene contemporaneamente nell'unica finestra "Database structure". Cliccando sul titolo di una tabella si inseriscono i dati relativi alla tabella, cliccando su un campo si personalizzano i dati del campo, eseguendo un trascinamento da un campo ad un altro si crea una relazione molti a uno dal campo di partenza a quello di destinazione del trascinamento, cliccando sulla linea che definisce una relazione si impostano le proprietà della relazione.

Consulta da questo link l’indice delle faq su 4th Dimension, MS Access e FileMaker Pro

1
Info Info 4th Dimension, MS Access e FileMaker Pro [1] NOMENCLATURA *
Con questa faq iniziamo a trattare alcuni degli argomenti che possono aiutare gli sviluppatori che vengono da un altro sistema di sviluppo.

Premesso che ogni strumento di programmazione ha i propri pregi e i propri difetti, l'obiettivo che ci possiamo prefiggere è quello di aiutare chi conosce già MS Access o FileMaker Pro e desideri passare a 4th Dimension, sfruttando in una certa misura le conoscenze già acquisite sulle altre piattaforme, trovando e analizzando sia i punti comuni che le sostanziali differenze. Le informazioni saranno ovviamente più precise su 4D, perché è l'ambiente che conosciamo meglio e su cui siamo ovviamente più aggiornati: è possibile dunque ad esempio che alcune caratteristiche di FileMakerPro 7 non siano citate completamente e/o correttamente.
Dopo questa necessaria introduzione passiamo all'argomento vero e proprio della faq.

NOMENCLATURA: ognuno dei tre sistemi di sviluppo definisce in maniera propria le componenti standard di un database: vediamo di uniformare il linguaggio.

- Tabelle: solo in FileMaker assumono una definizione diversa, cioè File.
- Campi: solo in Access assumono una definizione diversa, cioè Colonne.
- Maschere: i termini maschera, form, layout sono variamente utilizzati.
- Automazione: 4D usa degli oggetti chiamati metodi; Access usa macro e script Visual Basic; FileMaker calcoli automatici e script.
- Struttura: una finestra di relazioni è presente in tutte le piattafome; la struttura di un database 4th Dimension visualizza e permette l'inserimento di tabelle e campi.
- Lista di records: ognuno dei tre sistemi ha il suo modo di chiamare la lista di records: ad esempio se per 4D è il layout di output, per Access è la visualizzazione per foglio di calcolo.
- Ricerche: per costruire le query Access usa un editor, FileMaker effettua la ricerca da form, 4D esegue entrambi i tipi di ricerca con Query by example (che permette la ricerca sul form di inserimento dei dati) e Query editor (un editor visuale che permette la costruzione di una query)
- Selezione di records: ognuna delle tre piattaforme permette di gestire l'insieme dei record attualmente scelti.

Consulta da questo link l’indice delle faq su 4th Dimension, MS Access e FileMaker Pro

1
Info Info Uso delle risorse di 4D Client * con metodo aggiorna - signature
Usando 4D in versione client - server, sulla macchina client vengono creati dei file locali (che evitano traffico ridondante sulla rete). Se 4D Client va in crash o ha dei comportamenti inaspettati, il primo tentativo da fare è sicuramente quello di cancellare questi file temporanei, in modo da costringere 4D Client, al prossimo avvio, a ricrearli.

Per effettuare la cancellazione manualmente bisogna chiudere 4D Client, quindi cercare una cartella sul disco che si chiama come la struttura che stiamo usando e cancellarla.

Alcuni dei posti dove cercare questa cartella possono essere:

HD:System Folder:Application Support: (OS9)
/Library/Application Support/4D/ (OSX)
C:\WINDOWS\4D\ (WIN)

Un'altra strada percorribile per ottenere lo stesso risultato è quella di modificare il valore della risorsa "4D4D" nella struttura: in questo caso sarà il server a forzare l'aggiornamento, poiché il valore di questa risorsa deve essere identico fra Server e Client, e 4D Server effettua questo controllo ad ogni connessione.
La modifica del valore presente in questa risorsa si può effettuare aprendo la struttura con 4D Customizer Plus e cliccando sull'icona "Update".


1
Info Info Usare 4D Client come fosse l'Engine**
Da un colloquio avuto da poco con Anna Cernuschi di Italsoftware sono venuto a conoscenza di una caratteristica di 4D Server che volentieri condivido.

Se i vostri clienti si lamentano perché perché aprire un programma in versione server è troppo lungo (apri il client, scegli l'applicazione corretta, inserisci utente e password), potete creare un file di "scorciatoia" che eviti alcuni o tutti questi passaggi.

Aprite l'applicazione dal client e, dal design, andate nella finestra password. Selezionando un utente, si abiliteranno due voci di menu che permettono il salvataggio dell'utente con o senza password. Scegliamo ad esempio di salvare l'utente con password: dalla maschera standard di salvataggio diamo un nome e una posizione al file.
Il file creato è di tipo client connection: aprendolo con 4D Client l'utente farà accesso al programma senza dover eseguire la trafila precedentemente descritta, come se avesse l'eseguibile o la struttura in locale sulla sua macchina.


3

Accesso

User:
Pass: Accedi

Cerca

Se non trovi le informazioni che cerchi scrivi a aiuto@sviluppo4d.it

4D Principali

4D Discussioni

Faq random


Crediti

Dominio registrato da ZetaNet
Sito realizzato da Nexus srl
4D SQL 11.9.0 offerto da 4D & Italsoftware
Icone di FAMFAMFAM
Moderato da Umberto Migliore
301 utenti registrati

Pagina servita il 19/03/24 alle 12:44:19 Valid HTML 4.01! Valid CSS!

Mutuo Facile, iDigitalScout, iDigitalTags e altre app di Nexid srl per iPhone e iPad

Cidroid, distributore italiano lettori barcode per IOS Apple iPhone, iPod, iPad