Avatar billede Slettet bruger
09. november 2012 - 15:20 Der er 3 kommentarer

Import/update txt file vha VBA

Hej.

Her kommer en stor mundfuld, så derfor det lidt høje point tal.

Jeg er ved at lave mig en database, som skal importere ny "records" eller opdatere eksisterende "records" fra en txt fil.

Jeg har lavet øvelsen i excel, og skal nu gerne lave nogen lunde samme øvelse i access.

Ud over at jeg har lidt svært ved at få hul på opgaven i Access, er det også lidt problematisk at txt-filen er lidt speciel.

Inden den enkelte record skal importers, skal det tjekkes om emailen eksisterer i forvejen. Hvis den gør det, skal de andre felter i tabellen opdateres, hvis de er ændret.

Hvis ikke mailen ekstistere i forvejen, skal recorden skrives til tabellen.

Efterfølende skal det undersøges om der er nogen i tabellen, som ikke er i txt-filen og de skal ændres til Active = no.

De kolonner jeg har i min access tabel er:
Name
Title
Organization
Department
mail
Phone
IpPhone
Active (YES/NO)

Recorden ser ud som følger. Den starter altid med "dn:" men det er ikke altid at alle de andre linier er med.


dn: CN=Anne Ibsen,OU=LMN,OU=Locations,DC=dk,DC=testname,DC=dk
changetype: add
cn: Anne Ibsen
title: Key Account Manager
telephoneNumber: 004512345678
company: Org 1
mail: AI@org.dk
mobile: 004532165487

dn: CN=Adam Jensen,OU=LMN,OU=Locations,DC=dk,DC=testname,DC=dk
changetype: add
cn: Adam Jensen
title:: UmVnaW9uYWwgRGlyZWN0b3Ig4oCTIFNvdXRoIEF0bGFudGljIFJlZ2lvbg==
telephoneNumber: 004588568978
company: Org 2
mail: AJ@org.dk
mobile: 004587652489

Jeg håber, at der er en der har mod på at hjælpe mig, jeg tror bare jeg skal have hul på de enkele elementer, men man ved jo aldrig....
Avatar billede Slettet bruger
12. november 2012 - 01:51 #1
Jeg vil her præsentere en løsning med udspring i top-down måde at arbejde sig ned til detaljerne på:

Følgende subrutine hedder naturligvis noget andet i dit projekt og tabelnavn og filnavn kommer andet steds fra:
currentdb.execute er til start udkommenteret, så man kan se sql udtryk i debug vinduet. 'if 0 then' skal også erstattes af det udkommenterede der følger.
Funktionen filerecs tager som parameter, ud over filnavn og tabelnavn en liste af 3par:
    feltnavn i tekstfil,
    feltnavn i tabel
    type eller skip felt
Typen skal bruges for at omklamre feltindhold - f.eks gåseøjne til tekstfelter
filerecs giver et object der kan loopes gennem felter fra filen med.
 


Public Enum frDt
    skip = 0
    Text = 1
    Date = 2
End Enum

Sub usefilerecs()
    Const fn = "D:\home\dev\devel\access\filerecs.txt"
    Const tblN = "Person"
    Debug.Print "update " & tblN & " set Active=0"
    'CurrentDb.Execute "update " & tblN & " set Active=0"
    With fileRecs(fn, tblN, _
                            "dn", frDt.skip, frDt.skip, _
                            "changetype", frDt.skip, frDt.skip, _
                            "cn", "Name", frDt.Text, _
                            "title", "Title", frDt.Text, _
                            "telephoneNumber", "Phone", frDt.Text, _
                            "company", "Organization", frDt.Text, _
                            "mail", "mail", frDt.Text, _
                            "mobile", "IpPhone", frDt.Text)
        While Not .eor
            If 0 Then 'DLookup("mail", tblN, "mail='" & .rec!mail & "'") Then
                Debug.Print .sqlUpdate
            Else
                'CurrentDb.Execute .sqlInsert
                Debug.Print .sqlInsert
            End If
    Wend: End With
End Sub


filerecs initialiserer og returnerer et FileRecsLister object


Function fileRecs(filename, tableName, ParamArray fldUsage()) As FileRecsLister
    Set fileRecs = New FileRecsLister
    fileRecs.openfile filename
    fileRecs.tableName = tableName
    Dim i
    For i = 0 To UBound(fldUsage) Step 3
        fileRecs.fldNames.Add fldUsage(i), fldUsage(i + 1)
        fileRecs.fldUsage.Add fldUsage(i), fldUsage(i + 2): Next
End Function



FileRecsLister er en klasse - (altså insert 'class module' i vba editorens project explorer. Måske skal referencen 'microsoft scripting runtime' tilvælges (menulinie->tool->references)

Option Compare Database
Option Explicit

Public rec As Scripting.Dictionary
Private txtS As Scripting.TextStream
Public fldUsage As Scripting.Dictionary
Public fldNames As Scripting.Dictionary
Public tableName
Private keyV


Private Sub Class_Initialize()
    Set rec = New Scripting.Dictionary
    Set fldUsage = New Scripting.Dictionary
    Set fldNames = New Scripting.Dictionary
End Sub

Sub openfile(filename)
    With New Scripting.FileSystemObject
        Set txtS = .OpenTextFile(filename, ForReading, False)
    End With
End Sub
Property Get eor()
    Dim line, items
    rec.RemoveAll
    eor = txtS.AtEndOfStream
    If Not txtS.AtEndOfStream Then
        Do
            line = txtS.ReadLine
            If Len(line) Then
                items = Split(line, ":")
                rec.Add items(0), Trim(items(1)): End If
        Loop Until Len(line) = 0 Or txtS.AtEndOfStream
    End If
End Property


Function sqlInsert()
    Dim par, value, surr
    For Each keyV In rec.Keys
        If Not fldIsSkipped() Then
            surr = surrounding()
            par = par & fldNames(keyV) & ","
            value = value & surr & rec.item(keyV) & surr & ",": End If: Next
    sqlInsert = "Insert into " & tableName & " (" & par & "Active) values(" & value & "-1)"
End Function

Function sqlUpdate()
    Dim ass, surr
    For Each keyV In rec.Keys
        If Not fldIsSkipped() Then
            surr = surrounding()
            ass = ass & fldNames(keyV) & "=" & surr & rec.item(keyV) & surr & ",": End If: Next
    sqlUpdate = "Update " & tableName & " set " & ass & "Active=-1"
End Function

Private Function fldIsSkipped()
    'If fldUsage.Exists(keyV) Then If fldUsage(keyV) = frlDt.Skip Then fldIsSkipped = True
    If fldUsage.Exists(keyV) Then If fldUsage(keyV) = 0 Then fldIsSkipped = True
End Function

Private Function surrounding$()
    If fldUsage.Exists(keyV) Then
        Select Case fldUsage(keyV)
        Case frDt.Text
            surrounding = """"
        Case frDt.Date
            surrounding = "#"
        End Select: End If
End Function
Avatar billede Slettet bruger
12. november 2012 - 01:57 #2
Lige en tilføjelse - det kan være der er mere i det - at feltet 'dn' skal kunne nedbrydes og dele deraf bruges - jeg kan ikke se hvorfra Department skulle komme.

Desuden vil jeg påpege at det er den tomme linie i filen der bruges som postseperator (Loop Until Len(line) = 0 ...)
Avatar billede Slettet bruger
14. november 2012 - 09:26 #3
Mange tak.

Jeg får brug for et par dage til at kigge på det og så vender jeg tilbage.
Avatar billede Ny bruger Nybegynder

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.

Loading billede Opret Preview
Kategori
Dyk ned i databasernes verden på et af vores praksisnære Access-kurser

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester