Popolare tabella con campi calcolati da query

di il
8 risposte

Popolare tabella con campi calcolati da query

Buongiorno, è la prima volta che scrivo su qs forum. Grazie per l'opportunità. Non sono un programmatore professionale, ma saltuariamente per esigenze soprattutto lavorative sviluppo piccole routine in VBA, VBScript, di solito in ambiente Excel, Access.

Vorrei un consiglio su come impostare un progetto, utilizzando gli strumenti più razionali dove possibile.
Devo migrare un applicativo sviluppato su file Excel su diverso ambiente. Avrei optato per Access, ma sono aperto a consigli diversi. L'applicativo in Excel utilizza VBA (+ connessione Odbc) per importare dati attraverso query effettuate sul gestionale. Tali dati vengono utilizzati in un foglio per dare visibilità delle relative informazioni ad alcuni utenti, che sulla base di tali informazioni inserisco nello stesso foglio (in colonne a dx) delle loro ipotesi di lavoro. Infine ho sviluppato delle Functions che combinano i dati importati e le ipotesi degli utenti per fare una serie di elaborazioni, che utilizzano anche dati contenuti in diversi fogli dello stesso file. Il risultato di tali elaborazioni è il mio output.
I problemi attuali sono:
a) dimensione del file (13-15 MB, riducendo al minimo le formattazioni, anche se necessarie per la comprensione dei dati)
b) lentezza nel ricalcolo del file (le Functions in VBA inserite nelle celle sono abbastanza complesse)
Il foglio di lavoro principale ha circa 20.000 righe (variano in funzione del risultato query di importazione) e circa 80 colonne (di cui 30 derivanti dai dati importanti, 10 dai dati inseriti dagli utenti, 40 dalle elaborazioni con le Functions).

Vorrei passare ad MS Access. Ho impostato il lavoro in modo da poter fruire direttamente in Access delle query attraverso cui prima importavo i dati.
Ho una tabella che popolo dei dati utenti (che lascio in un file Excel esterno e aggiorno quando voglio allineare tutti i dati).
Alla fine con una query a cascata tra dati Odbc, tabella dati utenti e tabella risultati elaborazione ottengo le stesse informazioni del precedente file excel
Il problema purtroppo è la "trasposizione" delle Functions di Excel nell'equivalente codice VBA di Access, che utilizzo per popolare una Table. I tempi di elaborazione sono biblici. Già erano di alcuni minuti in Excel, ma qui occorre molto di più (e non ho ancora terminato la trasposizione delle Functions).

Come strategia cosa potrei provare a fare? cambiare piattaforma? utilizzare un motore esterno di calcolo e popolare poi la tabella? usare degli array?

Grazie!

8 Risposte

  • Re: Popolare tabella con campi calcolati da query

    Benvenuto nel forum di Access.

    1) Io ti suggerisco di leggere questo
    https://support.office.com/it-it/article/utilizzare-access-o-excel-per-gestire-i-dati-09576147-47d1-4c6f-9312-e825227fcaea

    2) Affinché gli utenti di Access possano comprendere il "cuore" del tuo problema, dovresti fornire informazioni "alla Access maniera", ossia:
    - di cosa parla il tuo database
    - se non riesci a fornire nomi di tabelle, avremmo almeno bisogno di vedere una decina di record per capirci di più

    3) Se vuoi ragionare secondo la logica Access, devi curare anche l'aspetto NORMALIZZAZIONE
  • Re: Popolare tabella con campi calcolati da query

    Grazie Forse potrei partire da un tema molto più specifico all'interno del tema più generale.
    Per popolare la Table "elab_bdg" parto da una query "BDG" e sulla base dei valori di ciascun record della query calcolo i valori dei campi della tab "elab_bdg" che popolo record per record. Nell'esempio qui sotto per il calcolo dei record della tabella "elab_bdg" utilizzo anche query su altre tabelle, nell'esempio la tabella "cls_merc". I tempi di elaborazione non sono "gestibili" (circa 450000-500000 elaborazioni, anche articolate con query annidate, per popolare la tabella).


    Sub prova()

    Dim db As Database
    Dim BDG As DAO.Recordset '

    anno_bdg = 2018
    Set db = CurrentDb()

    Set elab_bdg = db.OpenRecordset("elab_bdg", dbOpenTable)
    nr_records = elab_bdg.RecordCount
    If nr_records > 0 Then
    db.Execute "DELETE * FROM [elab_bdg]"
    End If

    Set qdf = CurrentDb.QueryDefs("BDG")
    'qdf.Parameters![anno bdg] = 2018
    Set rs = qdf.OpenRecordset

    nr_rcds = rs.RecordCount
    If nr_rcds = 0 Then GoTo uscita

    t0 = Timer

    rs.MoveFirst
    While Not rs.EOF
    elab_bdg.AddNew
    '01)
    elab_bdg.Fields("Articolo") = rs.Fields("Articolo")
    '02)
    elab_bdg.Fields("CodFor") = rs.Fields("CodFor")
    '03) Nr lotti di acquisto annuo:
    If rs.Fields("QtaTotMrpN+1") > 0 Then
    elab_bdg.Fields("NrLottiAcq") = IIf(rs.Fields("OrdMedN") > rs.Fields("Moq"), rs.Fields("OrdMedN"), rs.Fields("Moq")) / _
    rs.Fields("QtaTotMrpN+1")
    Else: elab_bdg.Fields("NrLottiAcq") = Null
    End If
    '04) VarPrInflasCls:
    anno_list = Year(rs.Fields("ValidoDal"))
    If anno_list < Year(Now()) And Not IsNull(rs.Fields("ValidoDal")) Then
    If anno_list < 2003 Then RifCls = "var.med" Else RifCls = rs.Fields("ClsMerc")
    strSQL = "SELECT * from [cls_merc] WHERE CodCls = '" & RifCls & "' AND Anno = " & anno_bdg - 1
    Set qry_cls = db.OpenRecordset(strSQL)
    qry_cls.MoveFirst
    IndClsAct = qry_cls.Fields("Indice")
    qry_cls.Close
    Set qry_cls = Nothing
    strSQL = "SELECT * from [cls_merc] WHERE CodCls = '" & RifCls & "' AND Anno = " & anno_list
    Set qry_cls = db.OpenRecordset(strSQL)
    qry_cls.MoveFirst
    IndClsPrec = qry_cls.Fields("Indice")
    qry_cls.Close
    Set qry_cls = Nothing
    elab_bdg.Fields("VarTime") = IndClsAct / IndClsPrec - 1
    Else:
    elab_bdg.Fields("VarTime") = 0
    End If
    '05) .........fino 31)
    '(ALTRE ELABORAZIONI CHE OMETTO MA CHE POPOLANO IN TOTALE 31 CAMPI INCLUSI QUELLI QUI GIA' POPOLATI)
    '
    elab_bdg.Update
    rs.MoveNext
    Wend
    rs.Close

    Set rs = Nothing

    t1 = Timer
    MsgBox ("T elab: " & t1 - t0)

    DoCmd.OpenQuery "BDG"

    uscita:

    End Sub
  • Re: Popolare tabella con campi calcolati da query

    Perché hai bisogno di popolare una tabella da una query?
    In Access le tabelle contengono solo valori primordiali, ossia quelli che solo l'utente fornisce. Le query provvedono a mostrare tutto ciò che l'utente desidera venga mostrato partendo dai dati primordiali delle tabelle...o di altre query (se la questione dovesse presentarsi particolarmente complessa).
  • Re: Popolare tabella con campi calcolati da query

    Non sto popolando la tabella con i dati della query, ma sto utilizzando i dati della query per calcolare valori con cui popolare la tabella. La tabella così popolata è l'output dell'applicazione...
  • Re: Popolare tabella con campi calcolati da query

    Se può essere utile per meglio indirizzare una soluzione, ho provato nel frattempo ad utilizzare degli Array ma non ho avuto risultati migliori, anzi il contrario. Ho copiato la query "BDG" in un array v1 e poi ho popolato un array V2 (dimensionato con lo stesso numero di "righe" di v1 e con un numero di colonne pari al numero di campi di "elab_bdg") usando le stesse routine che ho riportato sopra, senza miglioramenti. Qui sotto il codice

    Sub prova2()

    Dim rst As DAO.Recordset
    Dim xlApp As Excel.Application
    Dim v1 As Variant
    Dim v2 As Variant

    anno_bdg = 2018


    Set xlApp = CreateObject("Excel.Application")
    xlApp.Visible = False
    Set xlBook = xlApp.Workbooks.Add
    Set xlSheet = xlBook.Worksheets(1)

    Set rst = CurrentDb.OpenRecordset("BDG")
    xlSheet.Range("A1").CopyFromRecordset rst

    Set rTable = xlSheet.Range("A1").CurrentRegion
    v1 = rTable.Value
    a = rTable.Rows.Count
    b = rTable.Columns.Count

    Set rTable = Nothing
    xlApp.Visible = True
    xlBook.Close (False)
    xlApp.Quit
    Set xlSheet = Nothing
    Set xlBook = Nothing
    Set xlApp = Nothing

    ReDim v2(a, 31)

    For i = 1 To a
    v2(i, 1) = v1(i, 1) 'articolo
    v2(i, 2) = v1(i, 2) 'fornitore
    'Nr lotti di acquisto annuo:
    If v1(i, 13) > 0 Then
    v2(i, 3) = IIf(v1(i, 17) > v1(i, 20), v1(i, 17), v1(i, 20)) / v1(i, 13)
    Else: v2(i, 3) = Null
    End If
    'VarPrInflasCls:
    anno_list = Year(v1(i, 10))
    If anno_list < Year(Now()) And Not IsNull(v1(i, 10)) Then
    If anno_list < 2003 Then RifCls = "var.med" Else RifCls = v1(i, 26)
    strSQL = "SELECT * from [cls_merc] WHERE CodCls = '" & RifCls & "' AND Anno = " & anno_bdg - 1
    Set qry_cls = CurrentDb.OpenRecordset(strSQL)
    qry_cls.MoveFirst
    IndClsAct = qry_cls.Fields("Indice")
    qry_cls.Close
    Set qry_cls = Nothing
    strSQL = "SELECT * from [cls_merc] WHERE CodCls = '" & RifCls & "' AND Anno = " & anno_list
    Set qry_cls = CurrentDb.OpenRecordset(strSQL)
    qry_cls.MoveFirst
    IndClsPrec = qry_cls.Fields("Indice")
    qry_cls.Close
    Set qry_cls = Nothing
    v2(i, 4) = IndClsAct / IndClsPrec - 1
    Else:
    v2(i, 4) = 0
    End If
    Next i


    End Sub
  • Re: Popolare tabella con campi calcolati da query

    Facendo un riassunto vorrei che tu, a parte continuare a sostenere la necessità di salvare i dati calcolati da query a tabella, valuti la possibilità che questa strada possa essere errata.

    Tecnicamente tutto quello che è o può essere oggetto di calcolo NON SI.SALVA ma appunto lo si calcola con le query dai dati di base.

    Ci sono eccezioni a questo MUST per lo sviluppo di un Database, ma devi partire dalla teoria corretta e saper valutare quindi il modo giusto.

    Non so bene come sia la tua situazione che vedo confusa quindi mi fermo per consentirci di approfondire e riflettere.
    Nel tuo codice poi ci sono parti che riferiscono ad Excel che lascio a te....
  • Re: Popolare tabella con campi calcolati da query

    Grazie del riscontro. Proverò altre strade.
  • Re: Popolare tabella con campi calcolati da query

    Non cercare tanto invano... nulla è da inventare e la soluzione ti è già stata data.
    Ovviamente sei libero di sbagliare.
Devi accedere o registrarti per scrivere nel forum
8 risposte