AVVISO UTENTE

di il
15 risposte

AVVISO UTENTE

Ciao a tutti,

ho fatto un programma in access un pò di tenpo fa molto carino con l'aiuto di Alex e di alcuni che ora non ricordo più, funziona perfettamente.

Questo database l'ho messo in rete aziendale ed è condiviso a tre colleghi, quando si apre il file Access si può matricolare “staccare numeri sequenziali”, cercare commesse o fare una ricerca tramite la prima maschere dove ci sono dei pulsanti (macro).

Succede che quando tengo aperto il programma, ho bisogno che tutti i colleghi sanno che ho il file aperto, naturalmente se aprono il programma.

La domanda è semplice, c'è un sistema che quando ci sono due colleghi che utilizzano lo stesso programma può essere avvisato da un messaggio o un segnale come semaforo rosso o verde che viene indicato nella prima maschera d'apertura del programma?

Avevo pensato :

If Dir("nome_file.laccdb") <> "" Then
  MsgBox "Database Aperto!!"

End If

In questo modo chi apre il programma da sempre il messaggio di avviso “Database Aperto” e non va bene perchè potrei essere l'unico ad averlo aperto e il segnale non servirebbe, quindi è quando il secondo si collega deve essere avvisato e se esce dal programma l'avviso smette perchè c'è solo una persona che lo utilizza.

Grazie a tutti

15 Risposte

  • Re: AVVISO UTENTE

    Per Access nello specifivo non so ma quasi sicuramente trovi qualcosa (lock sulle tabelle, sui record, ecc), ci saranno altri che ti daranno indicazioni i piu' dettagliate, 

    comunque esiste un sistema ‘standard’ per questi casi, perche' sono la normalita' in TUTTI quei sistemi in cui piu' utenti accedono nello stesso momento (puoi ben immaginare la vastità infinita di casi di questo genere). 

    Quello che ti serve e' un ‘semaforo’ su una macchina che TUTTI vedono (il backend di access) .

    Windows mette a disposizioni API specifiche per questi casi:

    https://learn.microsoft.com/en-us/windows/win32/sync/semaphore-objects

    Non c'e' solo il semaforo, ci sono anche altri ‘oggetti di sincronizzazione’ che puoi utilizzare. Sono tutti concetti ‘standard’ nell'ambito della programmazione concorrente

    Access mette a disposizione le ‘transazioni’, altro concetto standard in TUTTI i DBMS (MySQL, oracle sql server,…) SPECIFICO per questi casi! 

  • Re: AVVISO UTENTE

    Prima di capire quale soluzione applicare, meglio chiarire il principio del problema…!

    Mi pare tu non abbia una gestione utenti, altrimenti nella Tabella LOGIN avresti registrato chi è loggato o meno…, in tal caso suggerirei di realizzare una minima gestione, avresti poi modo di sapere chi è loggato.
    Cosa diversa invece nel caso di Elaborazione dati Concorrente, ti suggerirei di evitarla a vantaggio di una gestione più semplice, chi accede in scrittura blocca gli altri, il problema con Access è che non funziona il BLOCCO singolo Record ma si blocca tutta la tabella, per questo si può ricorrere ad un arzigogolato e non nativo sistema di FLAG di Blocco del record in modifia.

    Come poi ti ha detto Migliorabile se è solo questione di segnalazione visiva si possono usare i sistemi di Windowd come i Semaphore, se poi devi anche Bloccare, allora si usano i Mutex:

    https://www.experts-exchange.com/articles/2104/Avoiding-running-multiple-instances-of-an-application.html

    Entrambi questi ultimi metodi, non sono nativi di Access non ci sono Classi come in altri linguaggi e si deve ricorrere alle API di Windows, sono decisamente meno intuitivi e semplici da usare.

  • Re: AVVISO UTENTE

    U;alternativa è usare il lock delle tabelle di Access per implementare l'equivalente del semaforo. 

    Dovrebbe bastare una tabellina di servizio

  • Re: AVVISO UTENTE

    Grazie Migliorabile e Alex, io non ho la gestione utenti, ma volevo solo una funzione che quando io utilizzo il file access in automatico gli altri sanno che lo sto usando, una comando che posso attivare e disattivare.

    Forse un semaforo è la soluzione visiva come rosso o verde.

    Per adesso non so come fare ma ci penso.

    Grazie

  • Re: AVVISO UTENTE

    Ciao,

    potresti provare una cosa di questo tipo… poco ortodossa, ma da verificare.

    Non posso provarla in rete con altri client, però se non vuoi crare una tabella di registrazione accessi, potresti ricavare dal file .laccdb il client che ha aperto l'applicazione (da verficare nel tuo contesto come procedere e se funziona come ho pensato)

    Per esempio… prova a provare a mettere in un modulo questa function che ritorna vero o falso: (da completare con i dovuti controlli per intercettare possibili errori)

    ' RETRIEVE CLIENT NAME IN THE FILE laccdb
    Public Function MyCheckLaccdb(strFullpathFileName As String) As Boolean
    ' variables define
    Dim fileNo As Integer
    Dim fileLine As String
    Dim strClientName As String
    Dim arySplit() As String
    
    ' check if exist
    If Dir(strFullpathFileName) <> "" Then
        ' file open
        fileNo = FreeFile
        Open strFullpathFileName For Input As #fileNo
        ' file Read
        If Not EOF(fileNo) Then
            Line Input #fileNo, fileLine
            arySplit = Split(fileLine)
        End If
        ' file close
        Close #fileNo
        ' retrieve client name
        If UBound(arySplit) > 0 Then strClientName = arySplit(0)
    End If
    
    ' check client and default return function value
    If Trim(strClientName) <> Environ("COMPUTERNAME") Then MyCheckLaccdb = False Else MyCheckLaccdb = True
    End Function

    Poi la richiami per esempio in questo modo:

    
    ' ESEMPIO
    If MyCheckLaccdb("YourFullPAthFileName.laccdb") Then
        MsgBox "Stesso PC Name"
    Else
        MsgBox "Pc con Name diverso"
    End If
    
    

    Non la vedo bene come soluzione, andare a leggere i file di access non è sempre cosa buona e giusta… comunque… io creerei una tabella di registrazione degli accessi dove puoi scrivere semplicemente il Client che ha aperto l'applicazione e poi quando la chiude elimina il record registrato. In questa tabella fai il test consultando se ci sono client collegati e chi sono. ;)

  • Re: AVVISO UTENTE

    Ciao BY65FRANCO, in effetti hai ragione, io avevo pensato quando io apro il file Access, e appena uno apre il file che è condiviso in automatico si apre una finestra di dialogo montale per esempio che avvisa “ATTENZIONE PIù UTENTI PRESENTI”.

    Oppure nella maschera di apertura del programma una cella o un pulsante che diventa rosso quando due utenti sono in apertura e quando risulta uno solo il segnale diventa verde.

  • Re: AVVISO UTENTE

    17/03/2024 - Tumi ha scritto:


    Ciao BY65FRANCO, in effetti hai ragione, io avevo pensato quando io apro il file Access, e appena uno apre il file che è condiviso in automatico si apre una finestra di dialogo montale per esempio che avvisa “ATTENZIONE PIù UTENTI PRESENTI”.

    Oppure nella maschera di apertura del programma una cella o un pulsante che diventa rosso quando due utenti sono in apertura e quando risulta uno solo il segnale diventa verde.

    Ciao, allora fai una tebella e in fase di apertura applicazione registri il nome del client.
    Dopo aver registrato il client che ha aperto l'applicazione, esegui il conteggio dei records presenti nella tabella.
    Se i records presenti sono > 1 accendi il semaforo, altrimenti no.

    Da verificare alcune cose, per esempio: 

    1.  quando si scrive il record con il nome del client, verificare sempre se già esiste perchè può accadere che ci sia stata una chiusura anomala dell'applicazione che non ha permesso la cancellazione del record di accesso
    2.  in fase di chiusura dell'applicazione, come ultima cosa, si leggerà la tabella e se esiste il record di accesso si elimina.

    E' una gestione semplice e banale che richiede veramente poco per essere sviluppata. ;)

  • Re: AVVISO UTENTE

    Ciao, 

    come detto in precedenza potresti fare una cosa molto semplice in questo modo dove:

    • viene creata una tabella con una colonna di tipo string dove salvare il nome dei pc client che hanno effettuato l'accesso all'applicazione
    • in fase di open dell'applicazione  creare un record nella tabella accessi
    • controllare e ritornare all'applicazione se ci sono più client che hanno eseguito l'accesso
      • iin questo caso è sufficiente avere come ritorno un valore booleano Vero o Falso per il quale accendi o spengi i tuoi semafori e/o altro
    • in fase di close dell'applicazione eliminare il record di accesso creato nella tabella

    Per ottemperare a quanto sopra riportato, puoi inserire nel progetto, in un modulo, delle funzioni public come da esempio:

    ' CHECK PC CLIENT ACCESS TO APPLICATION
    Public Function MyCheckClientAccess() As Boolean
    ' set return default value
    MyCheckClientAccess = False
    ' set table name
    Dim tblName As String
    tblName = "TblClientAccess"
    ' check if table exist in the database... and create table
    MyCreateClientAccessTable (tblName)
    ' insert your computer name in the pc client access table
    If DBEngine(0)(0).OpenRecordset("SELECT PcName FROM " & tblName & " WHERE PcName = '" & Environ("COMPUTERNAME") & "';", dbReadOnly).EOF Then
        DBEngine(0)(0).Execute "INSERT INTO " & tblName & " (PcName) VALUES ('" & Environ("COMPUTERNAME") & "');"
    End If
    ' check and return function value: true=there are multiple pc connected - False=there are no other pc connected
    Dim varResult As Variant
    varResult = DBEngine(0)(0).OpenRecordset("SELECT COUNT(*) FROM " & tblName & ";", dbReadOnly).Fields(0).Value
    ' set return value
    If varResult > 1 Then MyCheckClientAccess = True
    End Function
    
    ' CREATE TABLE PC CLIENT ACCESS
    Public Sub MyCreateClientAccessTable(tblName As String)
    ' set variables database
    Dim db As DAO.Database
    Dim tdf As DAO.TableDef
    Dim fld As DAO.Field
    ' set db
    Set db = CurrentDb
    ' check if extst
    On Error Resume Next
    Set tdf = db.TableDefs(tblName)
    On Error GoTo 0
    ' if not exist create table
    If tdf Is Nothing Then
        ' set tabledef
        Set tdf = db.CreateTableDef(tblName)
        ' add column
        Set fld = tdf.CreateField("PcName", dbText, 100)
        tdf.Fields.Append fld
        ' add table in the database
        db.TableDefs.Append tdf
    End If
    ' close
    Set fld = Nothing
    Set tdf = Nothing
    Set db = Nothing
    End Sub
    
    ' DELETE PC NAME IN THE APPLICATION CLIENT ACCESS TABLE
    Public Sub MyClosePcClientAccess()
    DBEngine(0)(0).Execute "DELETE FROM TblClientAccess WHERE PcName = '" & Environ("COMPUTERNAME") & "';"
    End Sub
    

    Qui trovi tre funzioni:

    1. MyCheckClientAccess - questa funzione si occupa di:
      1. controllare se esiste la tabella e se non esiste la crea con la funzione MyCreateClientAccessTable
    2. MyCreateClientAccessTable - questa funzione viene richiamata dalla funzione MyCheckClientAccess
      1. se non esiste la tabella viene creata
      2. nella tabella viene creata una sola colonna di tipo string dove verrà memorizzato il nome del pc client che ha aperto l'applicazione
    3. MyClosePcClientAccess - questa funzione viene richiamata in fase di chiusura dell'applicazione e ha il compito di eliminare il record che contiene il nome del pc client che aveva aperto l'applicazione

    ** Ho cercato di commentare il codice il più possibile per una maggiore comprensione, verificare eventuali errori e nel caso apportare le modifiche e/o correzioni


    Un esempio di come richiamare le funzioni sopra descritte:

    ' creating access to the application
    If MyCheckClientAccess Then
        MsgBox "Esistono più Client Collegati"		' Inserire le istruzioni per ACCENDERE IL SEMAFORO
    Else
        MsgBox "Non ci sono altri Client Collegati"	' Inserire le istruzioni per SPENGERE IL SEMAFORO
    End If

    Questa funzione viene richiamata in fase di open dell'applicazione e qui puoi gestire il valore di ritorno dove True = “Esistono più Client Collegati” e pertanto con questo valore puoi condizionare l'accensione del tuo semaforo per indicare che non si è soli. ;)
    La stessa provvede a memorizzare in un nuovo record il nome del proprio pc client che ha aperto l'applicazione.
    N.B. se ci sono più pc client con lo stesso nome e sono tutti collegati, il primo che esce dall'applicazione cancellerà non solo il proprio accesso ma anche tutti gli altri. Assicurarsi di avere i pc client con nome diverso, oppure memorizzare il mac address ( che  corrisponde ad un nome univoco ) dei pc cliente invece del nome, oppure modificare la stringa sql per eliminare solo il primo pc client che corrisponde al nome.


    ' eliminates access to the application when closing
    MyClosePcClientAccess
    

    Questa funzione viene richiamata in fase di chiusura dell'applicazione ed eliminerà il record creato in fase di apertura dell'applicazione.


    In definitiva non devi far altro che copiare le funzioni in un modulo e richiamarle come da esempi sopra riportati. 
    Non devi creare la tabella in quanto lo fa in modo automatico.
    Gestire il valore di ritorno True or False per accendere o spengere il semaforo … o altri metodi che preferisci.


    Una cosa che puoi fare con queste funzioni per esempio è quella di poter controllare a tuo piacimento o in automatico lo stato di connessioni, dei pc client, all'applicazione. 
    Per esempio puoi richiamare più volte nel corso dell'utilizzo dell'applicazione, la funzione MyCheckClientAccess  e valutare il valore di ritorno che restituisce: se ritorna False allora spengere il semaforo, questo vuol dire che gli altri client nel frattempo si sono scollegati dall'applicazione.
    Se invece ritorna True allora il semaforo rimane acceso (oppure si accende) ad indicare che altri client hanno aperto l'applicazione.

    Per esempio puoi anche richiamare tale funzione in automatico con l'oggetto Timer fissando un certo intervallo di tempo e ogni tot secondi ti fa la verifica e accende o spenge il semaforo.   Insomma, una cosa di questo tipo…. 
    Oppure puoi inserire il richiamo della funzione in un Pulsante e a tuo piacimento quando fai il click ti esegue la funzione e accende o spenge il semaforo.

    Una cosa da notare è quella di avere il semaforo acceso che indica l'esistenza di altri pc client che hanno aperto l'applicazione, ma di fatto sei l'unico ad aver aperto l'applicazione. Questo significa che uno o più pc cliente hanno aperto l'applicazione e hanno avuto una chiusura anomala della stessa. In questo caso rimarrà anche attivo il file .laccdb. Consultando la tabella accessi client puoi risalire al pc client che ha avuto tale anomalia.


    Questo è solo un semplice esempio di cosa potresti fare e se fa al caso tuo verifica il nome della tabella che viene creata che non vada in conflitto con le altre che hai nel progetto… inserisci eventuali controlli… prova e riprova, fai dei test e vedi se può andar bene… ;)


    N.B. puoi modificare la tabella aggiungendo tutte le colonne che desideri per memorizzare qualsiasi altri tipi di informazioni… per esempio la data/ora di acesso all'aplicazione , il nome del login di accesso al sistema operativo… ecc…ecc…
    Per apportare queste modifiche intervenire in questo passo del codice:


    Per esempio puoi implementare nel seguente modo le parti del codice per creare la tabella :

    ' if not exist create table
    If tdf Is Nothing Then
        ' set tabledef
        Set tdf = db.CreateTableDef(tblName)
        ' add column pc name
        Set fld = tdf.CreateField("PcName", dbText, 100)
        tdf.Fields.Append fld
        ' add column pc mac address
        Set fld = tdf.CreateField("PcMacAddress", dbText, 100)
        tdf.Fields.Append fld
        ' add column pc access date
        Set fld = tdf.CreateField("PcDate", dbDate)
        tdf.Fields.Append fld
        ' add table in the database
        db.TableDefs.Append tdf
    End If

    e la parte di inserimento record pc client in questo modo :

    ' insert your computer name in the pc client access table
    If DBEngine(0)(0).OpenRecordset("SELECT PcName FROM " & tblName & " WHERE PcName = '" & Environ("COMPUTERNAME") & "';", dbReadOnly).EOF Then
        DBEngine(0)(0).Execute "INSERT INTO " & tblName & " (PcName, PcMacAddress, PcDate) VALUES ('" & _
                                                            Environ("COMPUTERNAME") & "', '" & _
                                                            GetMacAddress & "', #" & _
                                                            Now() & "#);"
    End If

    A tal fine inserire nel modulo la function GetMacAddress per estrarre il mac address del pc client… per esempio:

    ' GET MAC ADDRESS PC
    Function GetMacAddress() As String
    ' set obj
    Dim objWMI As Object
    Dim colItems As Object
    Dim objItem As Object
    ' set default return value
    GetMacAddress = ""
    ' create obj wmi
    Set objWMI = GetObject("winmgmts:\\.\root\cimv2")
    ' get items
    Set colItems = objWMI.ExecQuery("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = True")
    ' read
    For Each objItem In colItems
        ' get mac address
        If Not IsNull(objItem.MACAddress) Then
            GetMacAddress = objItem.MACAddress
            Exit For
        End If
    Next objItem
    ' close
    Set objWMI = Nothing
    Set colItems = Nothing
    Set objItem = Nothing
    End Function

    A questo punto la tabella creata assumerà questo aspetto con le suddette info:

    Il nome del Pc client che ha aperto l'applicazione, il suo MacAddress e la data ora di accesso.
    (in questo caso le info riportate sono nomi  e indirizzi di fantasia)


    ( Sono solo esempi da verificare e testare )

  • Re: AVVISO UTENTE

    Ciao By45Franco, ci ho messo un pò per capire esattamente il modulo, sembra perfetto ma se si collegato un station volante non la vedo e non so chi sia.

    Stavo pensando una cosa molto semplice, il secondo che entra arriva un segnale nella maschera come segnale rosso e quando esce ritorna verde.

    Sembra semplice ma siccome il file è in rete in una cartella che i due colleghi possomo aprire il file access in qualsiai momento.

    Infatti è stato creato così perchè nel staccare dei codici è difficile che uno crea un duplicato come codice.

    Tutto qui va bene, il mio problema come ho scritto all'inizio e quando ho aperto il file e sto creando più commesse associato a dei codici,

    volevo evitare che uno mi stacchi un codice proprio in quel momento perchè ho bisogno che i codici che prendo sono tutti in serie.

    Non so se riesco a farmi spiegare, il segnale mi serve per capire che un'altro sta usando il file, io così posso avvisarlo dicendo aspetta un attimo che devo lavorare per una grossa commessa poi al mio segnale puoi usare i codici sucessivi.

    Grazie comunque.

  • Re: AVVISO UTENTE

    Cioa , 

    beh in questo caso lo scenario cambia…..

    22/03/2024 - Tumi ha scritto:


    Tutto qui va bene, il mio problema come ho scritto all'inizio e quando ho aperto il file e sto creando più commesse associato a dei codici,

    volevo evitare che uno mi stacchi un codice proprio in quel momento perchè ho bisogno che i codici che prendo sono tutti in serie.

    Bisognerebbe gestire il blocco tabella che però non mi sembra sia possibile su database in ms-access rispetto ad altri database.

    Potresti gestire questo scenario con un blocco personalizzato e quindi manualmente. Per esempio:

    • creare una tabella di Blocco
      • questa tabella avrà solo una colonna, per esempio di tipo string (oopure come da esempio precedente puoi inserire altr info)
    • quando accedi alla tabella dei Codici :
      • testare se nella tabella di Blocco esiste
        • se non esiste posso accedere al reperimento dei Codici
        • se esiste non posso accedere al reperimento dei Codici 

    A questo punto poniamo che per accedere ai Codici tu debba aprire una certa Form e a questo punto non voglio che altri possano accedere alla tabella dei Codici. Per esempio:

    • quando si apre questa Form si effettuano dei controlli del tipo:
      • interrogare la tabella di Blocco:
        • se esiste non posso accedere ai Codici in quanto qualcualtro ha l'accesso esclusivo
        • se non esiste allora posso accedere ai Codici e imposto l'accesso esclusivo :
          • si crea la tabella di blocco (da questo momento in poi nessun utente può accedere a tale funzionalità)
    • quando si chiude la Form :
      • si elimina la tabella di Blocco (da questo momento in poi gli altri utenti possono accedere a tale funzionalità)

    Prevedere un reset della tabella di Blocco :

    • creare una function per resettare la tabella di Blocco
      • proteggere con password l'accesso a questa funzionalità
        • eliminare la tabella di Blocco

    Questo consente di ripristinare gli accessi nel caso in cui un client abbia avuto accesso esclusivo alla tabella Codici e per qualche motivo l'applicazione si è chiusa in modo anomalo 


    Per esempio potresti anche mettere nella colonna del record della tabella di Blocco, chi ha eseguito l'accesso… il nome del computer, il nome dell'utente, la data ora in cui è stata creata la tabella di Blocco. 
    Quindi se necessario puoi risalire a chi sta tenendo bloccata la funzionalità di reperimento Codici.


    Per esempio si può attivare la tabella di Blocco mediante un Pulsante da inserire nella Form … però in questo caso non avrai una gestione automatica all'accesso della Form e potrebbero crearsi dei problemi non voluti.


    Questo è solo un semplice approccio per bloccare l'uso di una tabella e consentirlo in modo esclusivo solo a chi arriva prima ;-)

    Non so se può fare al caso tuo, però con un psistema di questo tipo, fin quando non finisci di gestire i Codici nessun altro può accedere a tale gestione.

    Se pensi sia una soluzione adatta alle tue esigenze, sei in grado di realizzarla oppure hai bisogno di una mano ? 
    Sono solo due righe di codice e un paio di funzioni da inserire e richiamare nei punti giusti del tuo codice.

    Fai sapere.

  • Re: AVVISO UTENTE

    Ciao,

    in merito al post precedente… ti ho preparato un esempio motlo banale  e lo puoi implementare come nell'esempio precedente con le info di chi ha bloccato l'operatività sulla tabella Codici:

    Per esempio :

    le funzioni sono tre :

    • MyBlockTest
      • esegue il test del Blocco se è attivo oppure non attivo
    • MyBlockActivate
      • esegue il controllo se attualmente è attivo il Blocco e restituisce :
        • True = il Blocco è Attivo (qualcuno tiene impegnata l'operatività sui Codici)
        • False = il Blocco è Disattivo (si può accedere all'operatività sui Codici)
    • MyBlockDeactivate
      • disattiva il Blocco dell'operatività sui Codici

    Per esempio come descritto nel post precedente puoi utilizzare le funzioni in questo modo:

    Attivare il blocco e/o verificare se il Blocco attualmente e attivo

    ' Test attivare il blocco della tabella
    Sub MyTestFunctionActivate()
    
    ' Attiva il blocco della tabella
    If MyBlockTest() Then
        MsgBox "Attualmente la tabella è Bloccata" --->>> QUI PUOI INSERIRE TUTTI I TUOI CONTROLLI NEL CASO IN CUI QUALCUNO HA BLOCCATO L'OPERATIVITA'
    Else											      .... ALTRIMENTI SI ATTIVA IL BLOCCO
        ' activate block table
        MyBlockActivate
    End If
    
    End Sub

    Disattivare il Blocco 

    ' Test disattivare il blocco della tabella
    Sub MyTestFunctionDeactivate()
    
    ' deactivate block table
    MyBlockDeactivate
    
    If Not MyBlockTest() Then
        MsgBox "La tabella è stata Sbloccata"   --->>> DA QUESTO MOMENTO IN POI IL BLOCCO NON E' PIU' ATTIVO E ALTRI POSSONO ACCEDERE
    End If
    
    End Sub
    

    Il richiamo di queste due funzioni le inserirai nei punti del tuo codice dove vorrai Bloccare e successivamente Sbloccare l'attività di gestione dei Codici


    Le funzioni da inserire, come al solito, in un modulo di codice sono :

    Option Compare Database
    Option Explicit
    
    ' CHECK IF THE BLOCK TABLE EXISTS
    Public Function MyBlockTest() As Boolean
    ' return default value (the block table does not exist)
    MyBlockTest = False
    ' test if the table exists
    Dim db As Database
    Dim tdf As TableDef
    On Error Resume Next
    Set db = CurrentDb
    Set tdf = db.TableDefs("TblBlock")
    If Not tdf Is Nothing Then MyBlockTest = True ' the block table exist
    ' reset variables
    Set tdf = Nothing
    Set db = Nothing
    End Function
    
    
    ' ACTIVATE TABLE BLOCK
    Public Sub MyBlockActivate()
    ' set variables database
    Dim db As Dao.Database
    Dim tdf As Dao.TableDef
    Dim fld As Dao.Field
    ' set db
    Set db = CurrentDb
    ' check if extst
    On Error Resume Next
    Set tdf = db.TableDefs("TblBlock")
    On Error GoTo 0
    ' if not exist create table
    If tdf Is Nothing Then
        ' set tabledef
        Set tdf = db.CreateTableDef("TblBlock")
        ' add column pc name
        Set fld = tdf.CreateField("PcBlock", dbText, 100)
        tdf.Fields.Append fld
        ' add column pc mac address
        Set fld = tdf.CreateField("PcMacAddress", dbText, 100)
        tdf.Fields.Append fld
        ' add column pc access date
        Set fld = tdf.CreateField("PcDate", dbDate)
        tdf.Fields.Append fld
        ' add table in the database
        db.TableDefs.Append tdf
    End If
    ' close
    Set fld = Nothing
    Set tdf = Nothing
    Set db = Nothing
    End Sub
    
    
    ' DEACTIVATE BLOCK TABLE
    Public Sub MyBlockDeactivate()
    ' chek if exist
    If MyBlockTest() Then
        Dim db As Database
        Set db = CurrentDb
        ' delete table
        db.TableDefs.Delete "TblBlock"
        db.Close
        ' close
        Set db = Nothing
    End If

    Implementazione inserendo le Info del Client come da post precedente

    Non servirebbe ma se vuoi anche sapere chi sta attualmente bloccando l'operatività sui Codici, allora puoi salvare nel record della tabella di Blocco le Info del client che attualmente sta tenendo bloccata l'opertività sui Codici. 
    Per popolare il record puoi fare riferimento al codice che nei post precedenti ti avevo esposto…
    Per esempio sarà sufficiente modificare la function di blocco in questo modo:

    ' ACTIVATE TABLE BLOCK
    Public Sub MyBlockActivate()
    ' set variables database
    Dim db As Dao.Database
    Dim tdf As Dao.TableDef
    Dim fld As Dao.Field
    ' set db
    Set db = CurrentDb
    ' check if extst
    On Error Resume Next
    Set tdf = db.TableDefs("TblBlock")
    On Error GoTo 0
    ' if not exist create table
    If tdf Is Nothing Then
        ' set tabledef
        Set tdf = db.CreateTableDef("TblBlock")
        ' add column pc name
        Set fld = tdf.CreateField("PcBlock", dbText, 100)
        tdf.Fields.Append fld
        ' add column pc mac address
        Set fld = tdf.CreateField("PcMacAddress", dbText, 100)
        tdf.Fields.Append fld
        ' add column pc access date
        Set fld = tdf.CreateField("PcDate", dbDate)
        tdf.Fields.Append fld
        ' add table in the database
        db.TableDefs.Append tdf
    End If
    ' close
    Set fld = Nothing
    Set tdf = Nothing
    Set db = Nothing
    
    ' insert your computer info
    DBEngine(0)(0).Execute "INSERT INTO TblBlock (PcBlock, PcMacAddress, PcDate) VALUES ('" & _
                                                    Environ("COMPUTERNAME") & "', '" & _
                                                    MyGetMacAddress & "', #" & _
                                                    Now() & "#);"
    End Sub
    

    Come puoi vedere alla fine della routine di creazione del blocco, viene inserita la riga sql di Insert INTO con il reperimento delle info da memorizzare.

    In questo caso si rende necessario aggiungere nel modulo di codice anche la funzione per reperire il MacAddress del client
    Esempio:

    ' GET MAC ADDRESS PC
    Function MyGetMacAddress() As String
    ' set obj
    Dim objWMI As Object
    Dim colItems As Object
    Dim objItem As Object
    ' set default return value
    MyGetMacAddress = ""
    ' create obj wmi
    Set objWMI = GetObject("winmgmts:\\.\root\cimv2")
    ' get items
    Set colItems = objWMI.ExecQuery("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = True")
    ' read
    For Each objItem In colItems
        ' get mac address
        If Not IsNull(objItem.MACAddress) Then
            MyGetMacAddress = objItem.MACAddress
            Exit For
        End If
    Next objItem
    ' close
    Set objWMI = Nothing
    Set colItems = Nothing
    Set objItem = Nothing
    End Function
    

    Fatto questo adesso nel file di Blocco hai anche le informazioni di chi stà impegnado l'operatività sui Codici e nella tabella potrai consultare le Info che saranno di questo tipo:


    Mi sembra tutto e come al solito è solo un esempio, quindi prova e riprova, controlla e inserisci i controlli dovuti e implementa ciò che ti occorre.

    Spero possa fare al caso tuo.
    Buon lavoro
    Ciao

  • Re: AVVISO UTENTE

    Ciao by65Franco, si vede che sei un programmatore appassionato, io sono al tuo primo livello come preparazione, mi piacerebbe programmare come lo fai tu.

    All'apertura della maschera si apre in questo modo.

    Poi vado nel comando inserimento ordini e si apre la maschera sucessiva, nella prima parte si compila i dati e nella seconda parte in automatico ho cretao un comando che quando assegno nella cella a tendina B/P il primo codice poi decido quanti ne ho bisogno, a questo punto con il tasto singolo o serie matricole in atumatico indico quanti ne ho bisogno e me li crea in automatico in serie.

    Pensavo che nella seconda mschera si deve attivare un blocco in modo che chi entra sa che lo sto usando.

    Io francamente ho seguito le tue istruzioni ma con più soluzioni.

    Sono un pò confuso.

    La creazione di una tabella che indica chi compila e da un avvio di blocco della maschera lo ritengo valido.

    Aggiungerei o due pulsanti di comando che blocca e sblocca e nello stesso tempo so chi ha aperto il progamma.

    Quindi se io apro il programma, il secondo che apre il programma vede che sono io che ho aperto il programma, io potrei disattivare il blocco se non lo ritengo necessario mantenerlo bloccato.

    Qundo uno si muove da un record ad altro per una ricerca, la maschera si blocca nel modo che non si possono alterare i dati, solo con il pulsante “Modifica record” posso disattivare per modificare i dati.

    In questa machera potrei sapere chi ha aperto adesso il programma, ho assegnato all'inizio della machera una cella a tendina il nome per chi compilato i dati.

    Speriamo di averti spiegato in un modo semplice, io l'ho pensato un pò di tempo fa questo programma ma senza questo aviso perchè non era importante e rischioso.

    Grazie per la tua disponibilità e cortesia.

    Se potessi darmi una mano ne sarei grato.

  • Re: AVVISO UTENTE

    Ciao,

    posso darti la logica e un consiglio, ma vedo che sei già sulla buona strada.

    Vediamo se ho capito….

    24/03/2024 - Tumi ha scritto:


    Poi vado nel comando inserimento ordini e si apre la maschera sucessiva, nella prima parte si compila i dati e nella seconda parte in automatico ho cretao un comando che quando assegno nella cella a tendina B/P il primo codice poi decido quanti ne ho bisogno, a questo punto con il tasto singolo o serie matricole in atumatico indico quanti ne ho bisogno e me li crea in automatico in serie.

    Quando esegui il comando in questo punto “ho cretao un comando che quando assegno nella cella a tendina B/P il primo codice poi decido quanti ne ho bisogno
    All'inizio della routine inserirei la verifica del blocco e se non è attivato allora lo attivo.  Poi a fine di questa routine elimino il blocco. 

    Esempio: Poniamo che nel codice della form il tuo comando si chiama ComandoDP

    Private Sub ComandoBP()
    ' controlla se la tabella è bloccata e in questo caso emette un messaggio e esce dalla routine
    ' altrimenti se la tabella non è bloccata, allora verrà bloccata fino alla fine della routine
    
    ' check block
    If MyBlockTest() Then
        MsgBox "Funzionalità attualmente bloccata da:" & MyGetBlockInfo, vbCritical, "Info"
        Exit Sub
    Else
        ' activate block table
        MyBlockActivate
    End If
    
    ' esegui il tuo codice per reperire i codici di cui hai bisogno
    ' ...
    ' .....
    ' .......
    ' .....
    ' ...
    
    ' alla fine dell'assegnazione dei codici si elimina il blocco a questa funzionalità
    
    ' deactivate block table
    MyBlockDeactivate
    End Sub

    Se qualcuno ha già impegnato la tabella allora ti restituisce un messaggio di questo tipo e con Exit Sub esce dal ComandoBp

    In questo modo si ha un accesso esclusivo alla funzionalità che hai descritto fino a quando non hai completato il comando.
    Quindi in automatico blocca e sblocca la tabella (o per meglio dire, questa tua funzionalità per reperire i codici)


    Riprendi il codice che ho aggiornato rispetto alla prima versione: (questo codice lo devi inserire in un Modulo di Codice)

    ' CHECK IF THE BLOCK TABLE EXISTS
    Public Function MyBlockTest() As Boolean
    ' return default value (the block table does not exist)
    MyBlockTest = False
    ' test if the table exists
    Dim db As Dao.Database
    Dim tdf As Dao.TableDef
    On Error Resume Next
    Set db = CurrentDb
    Set tdf = db.TableDefs("TblBlock")
    If Not tdf Is Nothing Then MyBlockTest = True ' the block table exist
    ' reset variables
    Set tdf = Nothing
    Set db = Nothing
    End Function
    
    ' ACTIVATE TABLE BLOCK
    Public Sub MyBlockActivate()
    ' set variables database
    Dim db As Dao.Database
    Dim tdf As Dao.TableDef
    Dim fld As Dao.Field
    ' set db
    Set db = CurrentDb
    ' check if extst
    On Error Resume Next
    Set tdf = db.TableDefs("TblBlock")
    On Error GoTo 0
    ' if not exist create table
    If tdf Is Nothing Then
        ' set tabledef
        Set tdf = db.CreateTableDef("TblBlock")
        ' add column pc name
        Set fld = tdf.CreateField("PcBlock", dbText, 100)
        tdf.Fields.Append fld
        ' add column pc mac address
        Set fld = tdf.CreateField("PcMacAddress", dbText, 100)
        tdf.Fields.Append fld
        ' add column pc access date
        Set fld = tdf.CreateField("PcDate", dbDate)
        tdf.Fields.Append fld
        ' add table in the database
        db.TableDefs.Append tdf
    End If
    ' close
    Set fld = Nothing
    Set tdf = Nothing
    Set db = Nothing
    ' insert your computer info
    DBEngine(0)(0).Execute "INSERT INTO TblBlock (PcBlock, PcMacAddress, PcDate) VALUES ('" & _
                                                    Environ("COMPUTERNAME") & "', '" & _
                                                    MyGetMacAddress & "', #" & _
                                                    Now() & "#);"
    End Sub
    
    ' DEACTIVATE BLOCK TABLE
    Public Sub MyBlockDeactivate()
    ' chek if exist
    If MyBlockTest() Then
        Dim db As Dao.Database
        Set db = CurrentDb
        ' delete table
        db.TableDefs.Delete "TblBlock"
        db.Close
        ' close
        Set db = Nothing
    End If
    End Sub
    
    ' GET MAC ADDRESS PC
    Function MyGetMacAddress() As String
    ' set obj
    Dim objWMI As Object
    Dim colItems As Object
    Dim objItem As Object
    ' set default return value
    MyGetMacAddress = ""
    ' create obj wmi
    Set objWMI = GetObject("winmgmts:\\.\root\cimv2")
    ' get items
    Set colItems = objWMI.ExecQuery("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = True")
    ' read
    For Each objItem In colItems
        ' get mac address
        If Not IsNull(objItem.MACAddress) Then
            MyGetMacAddress = objItem.MACAddress
            Exit For
        End If
    Next objItem
    ' close
    Set objWMI = Nothing
    Set colItems = Nothing
    Set objItem = Nothing
    End Function
    
    ' GET BLOCK INFO
    Public Function MyGetBlockInfo() As String
    ' return default function value
    MyGetBlockInfo = ""
    ' open recordset
    Dim rs As Dao.Recordset
    Set rs = DBEngine(0)(0).OpenRecordset("SELECT * FROM TblBlock;")
    ' read info
    If Not rs.EOF Then
        ' return function value
        MyGetBlockInfo = vbCrLf & vbCrLf & "Pc Name " & rs.Fields(0) & vbCrLf & "MACAddress " & rs.Fields(1) & vbCrLf & vbCrLf & "DateTime " & rs.Fields(2)
    End If
    ' close
    rs.Close
    Set rs = Nothing
    End Function

    Se non va bene con questa logica che non richiede pulsanti o altro, ma fa tutto in automatico, fai sapere.
    Ciaooo

  • Re: AVVISO UTENTE

    Ciao, non riesco a far partire il programma,  forse ti ho fatto perdere del tempo.

    Il file access è in una cartella in rete dove alcuni dei miei colleghi posono aprirlo dal proprio pc e usare il programma.

    Ma non possiamo sapere chi ha aperto il programma, un giorno potrebbe aprirlo un'altro collega quindi anche se sapessi il nome del computer nel modulo dovrei modificare i nomi, insomma non credo che sia efficace, forse mi sfugge qualcosa.

    Quando apro il file access lui crea un file laccdb fino a qui usando il modulo:

    If Dir("nome_file.laccdb") <> "" Then
      MsgBox "Database Aperto!!"       sarebbe perfetto!!!

    ma l'avviso arriva sempre, ci vorrebbe che quando il secondo utente apre il file arriva "l'avviso", per esempio ci vorrebbe un qualcosa che quando il secondo utente apre il file crea un altro file tipo come file.laccdb ma con un nome diverso in modo che da li dobrebbe arrivare l'avviso.

    Grazie per la tua preziosa assistenza e aiuto, se ti viene in mente una idea ne sarei contento.

    :-) grazie

Devi accedere o registrarti per scrivere nel forum
15 risposte