Newsgroup: it.comp.appl.access
Titolo: Creazione tabella estraendo i dati da un campo

Buongiorno,
ho una tabella con 5 campi di cui il quinto campo contiente un numero indefinito di codici prodotti tutti separati dal segno di ";".
Es: C1122;C0012;
Il numero dei codici non è definito ma lo posso sapere in anticipo contando i ";"
Il mio obiettivo è creare una tabelle così composta:
Nell'esempio sopra riportato con due codici prodotto dovrei inserire nella nuova tabella 5 campi iniziali dove i primi 4 sono uguali per entrambi i record mentre l'ultimo è uguale, nel primo record, al codice "C1122" e nel secondo al codice "C0012".
Se qualcuno mi può dare una dritta, vi ringrazio.
Ciao
 


speriamo che ti rispondano presto, altirmenti provo a cercare una soluzione,certo che dovresti  lavorare con DAO/ADO. è un pò complessa la cosa....ciao

Il giorno lunedì 10 settembre 2018 13:10:07 UTC+2, Fabio Fucci ha scritto:

ho riscritto il post, da un po' di tempo vedo invii parziali ...
 
allora: 
 
SE i codici (come dovrebbe essere) hanno sempre lo stesso numero di caratteri 
E c'è un solo carattere separatore 
(NON importa quale sia, e può essere anche assente al termine della stringa) 
 
questa routine dovrebbe andare bene: 
 
Sub daTANTIaUNO() 
Dim rs As DAO.Recordset 'NECESSARIO RIFERIMENTO libreria DAO 
CODICEchar = 6 'lunghezza codice SEPARATORE COMPRESO (NUMERO comunque FISSO !)
strSQL = "select * from tabMoltiCodici" 
Set rs = CurrentDb.OpenRecordset(strSQL) 
rs.MoveFirst 
DoCmd.SetWarnings False 
Do While Not rs.EOF 
    CODICIchar = Len(rs!C5mc) 'lunghezza campo codici multipli 
    For i = 1 To CODICIchar Step CODICEchar 
        DoCmd.RunSQL "INSERT into tabSingoloCodice (C1sc, C2sc, C3sc, C4sc, C5sc) values ('" & rs!C1mc & "', '" & rs!C2mc & "', '" & rs!C3mc & "', '" & rs!C4mc & "', '" & Mid(rs!C5mc, i, CODICEchar - 1) & "')" 
'NOTA BENE QUI: CODICEchar - 1 si intende che il separatore è UN SOLO CARATTERE
    Next 
    rs.MoveNext 
Loop 
DoCmd.SetWarnings True 
Set rs = Nothing 
End Sub 
 
ribadisco qualche definizione (intuitiva ?) 
 
tabMoltiCodici->tabella con la stringa multiCodice 
tabSingoloCodice->tabella con la stringa singoloCodice 
da C1mc a C5mc: NOMI CAMPO tabella multiCodice 
da C1sc a C5sc: NOMI CAMPO tabella singoloCodice 
 
comando INSERT (dopo DoCmd.RunSQL): E' UNA RIGA UNICA !!! 
TUTTI I CAMPI SONO CONSIDERATI STRINGA 
(se ci sono numeri e date occorre togliere o cambiare l'apice nella INSERT !!! 
se ci sono date o valori numerici decimali occorre approntare una funzione di "adeguamento dati" per la INSERT) 
 
ovviamente è considerato che un singolo lancio 
(testato su una copia dati) "risolva tutto" 
 
NON E' PRESENTE la gestione errori 
che, se avvengono, lasciano DoCmd.SetWarnings false in ACCESS 
(e l'oggetto rs aperto ...) 

A parte le soluzioni proposte... le 2 tabelle sono prive di relazione...?
Come puoi poi recuperare il legame iniziale dopo questa scissione...?
Boh qualche cosa che scricchiola mi pare ci possa essere...
 
@Alex


Bellissimo, se invece i codici non sono tutti uguali in lunghezza ma separati dal carattare "-"
si può usare la funzione split (come mi disse Alex in un post di pochi giorni fa....spero di non aver scritto una cazzata)
 
Dim varItem  as Variant
Dim varItems Ad Variant
 
VarItems= SPLIT(rs!C5mc,"-")
For each varItem in varItems
 DoCmd.RunSQL "INSERT into tabSingoloCodice (C1sc, C2sc, C3sc, C4sc, C5sc) values ('" & rs!C1mc & "', '" & rs!C2mc & "', '" & rs!C3mc & "', '" & rs!C4mc & "', '" & varItem & "')"
Next
 
ciao

 VarItems= SPLIT(rs!C5mc,",")



ho fatto un test sulle tabelle preparate per l'occasione,
poiché NON ho mai usato la funzione SPLIT
 
allora, come anche Alex confermerà, succede questo:
 
SE il separatore è ANCHE l'ultimo carattere della stringa multicodice
occorre un accorgimento per evitare la stringa nulla
 
quindi (senza ripetere i significati dei vari nomi)
CASO CON STRINGA MULTICODICE CHE TERMINA CON IL SEPARATORE
 
Sub daTANTIaUNO_S()
Dim rs As DAO.Recordset 'NECESSARIO RIFERIMENTO libreria DAO
strSQL = "select * from tabMoltiCodiciS"
Set rs = CurrentDb.OpenRecordset(strSQL)
rs.MoveFirst
DoCmd.SetWarnings False
Do While Not rs.EOF
    varItems = Split(rs!C5mc, ",")
    For Each varItem In varItems
    If Len(varItem) > 0 Then DoCmd.RunSQL "INSERT into tabSingoloCodiceS (C1sc, C2sc, C3sc, C4sc, C5sc) values ('" & rs!C1mc & "', '" & rs!C2mc & "', '" & rs!C3mc & "', '" & rs!C4mc & "', '" & varItem & "')"
    Next
    rs.MoveNext
Loop
DoCmd.SetWarnings True
Set rs = Nothing
End Sub
 
 
CASO CON STRINGA MULTICODICE CHE NON TERMINA CON IL SEPARATORE
 
Sub daTANTIaUNO_S()
Dim rs As DAO.Recordset 'NECESSARIO RIFERIMENTO libreria DAO
strSQL = "select * from tabMoltiCodiciS"
Set rs = CurrentDb.OpenRecordset(strSQL)
rs.MoveFirst
DoCmd.SetWarnings False
Do While Not rs.EOF
    varItems = Split(rs!C5mc, ",")
    For Each varItem In varItems
    DoCmd.RunSQL "INSERT into tabSingoloCodiceS (C1sc, C2sc, C3sc, C4sc, C5sc) values ('" & rs!C1mc & "', '" & rs!C2mc & "', '" & rs!C3mc & "', '" & rs!C4mc & "', '" & varItem & "')"
    Next
    rs.MoveNext
Loop
DoCmd.SetWarnings True
Set rs = Nothing
End Sub
 
 
infine, anche per dare riscontro alle perplessità di Alex,
ripeto che questa è una routine da "un colpo e via"
(ricollocazione dei dati DA tabella A tabella, e tutto si chiude lì)
 
se la tabella multicodice viene alimentata in continuo
la routine è sempre valida ma bisogna gestire le righe trasferite
(cancellazione a mano ?, da query ?, aggiunta di un flag ?)


Giorgio, quello che hai esposto è corretto, ma non tutto.
Ipotizzo, anche se non lo hai inserito nel Codice, che la Variabile [varItems] sia stata pensata come VARIANT...
In tal caso l'ultimo ITEM del Variant Array da SPLIT conterrebbe un NULL e la funzione LEN su un Variant NULL andrebbe in Errore.
 
Nulla di grave, basta scrivere così:
 
If Len(varItems  & vbNullstring)>0 then.....
 
IN seconda battuta, al fine di non dover usare SetWarnings... ed evitare gli Avvisi si può agevolmente passare il predicato SQL al metodo EXECUTE membro di Database, accessibile quindi:
 
DbRngine(0)(0).Execute "...."
oppure
Dim dbs As DAO.Database
Set dbs=CurretDb()
dbs.Execute "...."
 
Questo metodo consente di essere inserito in TRANSAZIONE, e, applicando il parametro dbFailOnError di gestire il RollBack, ma anche e soprattutto, di avere la certezza che l'azione ha agito su UN Record(o più a seconda) leggendo la proprietà RecordsAffected membro sempre di Database o di QueryDef...
 
Saluti
@Alex
 
@Alex

Il giorno lunedì 10 settembre 2018 13:10:07 UTC+2, Fabio Fucci ha scritto:

Ciao Fabio,
per fare quello che chiedi, basta una semplice routine con l'aiuto di una matrice unidimensionale e la funzione Split.
 
Al seguente link puoi scaricare una piccola demo:
 
https://1drv.ms/u/s!Atj5hqpmt9_fgnKN9OmEOr5Ufd-y
 
 
Vladimiro


Ciao Fabio,
ho notato solo ora che non ti interessa visualizzare il record contenente un valore nullo nel Campo_E dal momento in cui il";" è parte finale della stringa del Campo5 della Tbl1.
 
Basta uscire dal ciclo For - Next che implementa i primi quattro campi della tbl2 quando si crea la suddetta situazione:
 
Set rs1 = CurrentDb.OpenRecordset("Select * From Tbl1 ", dbOpenDynaset, dbSeeChanges)
Set rs2 = CurrentDb.OpenRecordset("Tbl2", dbOpenDynaset, dbSeeChanges)
 
Do Until rs1.EOF
    sArray = Split(rs1!Campo5, ";")
        For j = LBound(sArray) To UBound(sArray)
            rs2.AddNew
                rs2!Campo_E = Split(rs1!Campo5, ";")(j)
                    If Len(rs2!Campo_E & "") = 0 Then
                        Exit For
                    End If
                For i = 1 To rs1.Fields.Count - 2
                    rs2(i) = rs1(i)
                Next i
            rs2.Update
        Next j
rs1.MoveNext
Loop
 
rs1.Close
rs2.Close
Set rs1 = Nothing
Set rs2 = Nothing
 
Vladimiro