17. marts 2004 - 08:24Der er
18 kommentarer og 1 løsning
Data fra Access til Excel
Hejsa
Jeg har et regneark som består at et "varenummer" og en "2003pris". I en access database har jeg samme "varenummer" og en "2004pris". Udfordringen består i at kæde data fra min access database sammen med data fra mit Excel regneark.
Da min Access database består af ca. 200000 poster, ville jeg gerne undgå at skulle indsætte alle disse poster i et regne ark, hver gang der kom en ny database med nye priser. Derfor ser en en løsning i retning af en makro, som er istand til at læse værdien varenummer i A1, A2, A3.. osv.(evt. between) og dermed lave et SQL statement som kan slå prisen op i access og aflevere resultatet i celle C1, C2, C3 osv ..
Jeg fandt denne makro herinde, som måske kan hjælpe på vej :-)
Sub GetTable() Dim Db As Database Dim Rs As Recordset Dim Ws As Worksheet Dim Path As String Set Ws = ActiveSheet Dim sqlstr As String
'*** sti til database *** Path = "D:\db1.mdb" 'Her indsætter du navn og sti på din accessdatabase
'*** SQL-streng med reference til A2 *** '**** dvs at den skal finde den record i access hvor Varenummeret er lig med det du har skrevet i A1 sqlstr = "SELECT * FROM 2004 WHERE DESCP =" & Range("A2").Value & ";"
'*** Hent data *** Set Db = Workspaces(0).OpenDatabase(Path, ReadOnly:=True) Set Rs = Db.OpenRecordset(sqlstr)
'*** Indsæt VareTekst i A5 og Disponent i A7 *** Ws.Range("G2") = Rs.Fields("DESCP") Ws.Range("H2") = Rs.Fields("EPL2004")
'*** luk databasen igen *** Rs.Close Db.Close End Sub
Flere ting i nedenstående skal skiftes ud - Ret stien og navnet på databasen - Ret tabelnavn (et sted) - Ret feltnavn (to steder) - Skal prisen ikke indsættes i kolonne B men f.eks. i D - så ret Offset(0, 1) til Offset(0, 3)
Sub GetPrices() Dim dbPrice As Database Dim rsData As Recordset Dim sPath As String Dim sSQL As String Dim sSQLTemp As String Dim rCell As Range
'*** sti til database *** sPath = "D:\db1.mdb" 'Her indsætter du navn og sti på din accessdatabase
'*** SQL-streng hvor XXX bliver udskiftet *** sSQL = "SELECT * FROM tabelnavn WHERE feltnavn = XXX;"
For Each rCell In ActiveSheet.UsedRange.Columns(1).Cells
Ja, der vil sikkert være nogle problemstillinger, som kan give fejl....
Jeg har ikke tid til at kigge yderligere på det nu, men du er velkommen til at sende arket til mig med henvisning til spørgsmålnummeret, så vil jeg kigge på det i aften. Find min email her www.win-consult.com.
'*** Hent data *** Set dbPrice = Workspaces(0).OpenDatabase(sPath, ReadOnly:=True) Set rsData = dbPrice.OpenRecordset(sSQLTemp)
'*** Indsæt pris i kolonne B *** If Not rsData.RecordCount = 0 Then rCell.Offset(0, 3).Value = rsData.Fields("EPL2004").Value End If '*** Luk recordset *** rsData.Close
Next rCell
'*** luk databasen igen *** dbPrice.Close
'*** Ryd op *** Set rCell = Nothing Set Rs = Nothing Set Db = Nothing End Sub
Det kunne måske misforståes. Det er absolut ikke ment som kritik. Jeg mener bare at man burde kunne nøjes med at hente det hele een gang og derefter gøre noget smart.
Sub GetPrices() Dim dbPrice As Database Dim rsData As Recordset Dim sPath As String Dim sSQL As String Dim rCell As Range Dim lRecord As Long
'*** sti til database *** sPath = "D:\VBA-Test\Jan Schneider\db1.mdb" 'Her indsætter du navn og sti på din accessdatabase
'*** SQL-streng hvor XXX bliver udskiftet *** sSQL = "SELECT * FROM 2004;"
'*** Hent data *** Set dbPrice = Workspaces(0).OpenDatabase(sPath, ReadOnly:=True) Set rsData = dbPrice.OpenRecordset(sSQL)
If Not rsData.RecordCount = 0 Then For Each rCell In ActiveSheet.UsedRange.Columns(1).Cells
rsData.MoveFirst Do While Not rsData.EOF If rCell.Value = rsData.Fields("DESCP").Value Then rCell.Offset(0, 3).Value = rsData.Fields("EPL2004").Value Exit Do End If rsData.MoveNext Loop
Next rCell End If
'*** luk databasen igen *** rsData.Close dbPrice.Close
'*** Ryd op *** Set rCell = Nothing Set rsData = Nothing Set dbPrice = Nothing End Sub
Istedet for at move igennem kunne man måske benytte .find Jeg har fået det til at virke, men synes ukke at hastighed imponerer (nu skal der også meget til :-) )
teststr = "DESCP = '" & rCells.value & "'" rsData.Find teststr, , adSearchForward, 1 If rsData.EOF Then rCell = "not found" rsData.MoveFirst Else rCell = rsData!ELP2004 End If
Jeg har forsøgt med rsdata.seek som skulle være meget hurtig, men kan ikke rigtig komme ind på den...
Ja, det kan man godt. Dog synes jeg at gennemløb af data, som du har i et objekt er så hurtig, at der ikke vindes proformance ved at gøre det anderledes. Mængden af data kan selvfølgelig blive SÅ stor, at det måske kan mærkes.
Det viser sig at det bedre kan betale sig at lave flere SQL forspørgsler, frem for at læse hele databasen ind i et object! Min DB fylder 26Mb (250000 poster)komprimeret og optimeret og det tager derfor evigheder at læse det hele det hele ind. Benytter jeg den først forslåede metode sker det hele i en ruff .. næsten :-)
Super - bemærk blot, at der er en fejl under RYD OP i den makro, som laver mange SQL-forespørgsler. Det skal se således ud:
'*** Ryd op *** Set rCell = Nothing Set rsData = Nothing Set dbPrice = Nothing
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.