Aanmaken back-end en front-end

  • Onderwerp starter Onderwerp starter Timg
  • Startdatum Startdatum
Status
Niet open voor verdere reacties.

Timg

Gebruiker
Lid geworden
1 apr 2011
Berichten
32
Beste,

Ik heb een database aangemaakt die toegankelijk moet zijn voor 4 verschillende groepen.
1 groep voor het bij aanvullen met gegevens. (Werknemers)
1 groep voor het bijwerken van gegeven. (Portiers)
1 groep voor het analyseren van de ingevulde gegevens.
1 groep voor het wijzigen van een lijst, die bij in de database staat. (Deze lijst kan door alle groepen bekeken worden.)

Ik moet dus 4 front-ends maken die naar 1 back-end verwijzen.
Het probleem is dat:
- Ik dit nog nooit gedaan heb.
- De back-end moet op een netwerkschijf komen te staan, waar iedereen lees en schrijfrechten op heeft, maar voor de ene is dit de I-schijf en de ander de K of ... schijf. :s

Kan iemand mij een paar tips geven over hoe ik dit het best aanpak?
Ik moet waarschijnlijk iedereen gaan verplichten om dezelfde benaming te gebruiken, of is er een andere manier om dit aan te pakken?

Als ik de front-ends aangemaakt heb, kan deze dan bij iedereen op het bureaublad geplaatst worden? Of is dit plaats gebonden en kan dat bij iedereen anders zijn?

Alvast bedankt,
Timg
 
Beste,

De onderstaande codes heb ik vroeger na langdurig googlen in al mijn programma's verwerkt en werkt voorzover ik weet prima.

Code:
Public P_BackendPath  as string 
Public Const C_BEName as string = "pbbe"          ' Het eerste gedeelte van de backend naam bijv pbbe, de suffix is altijd .data 

'
.
. 
.
P_backendPath = "j:\data\pbbe.data"     ' 
if not filexist (P_backendpath ) then selectbackend(P_backendPath) 


If Not TestLinks Then
    Call RemoveLinks
    Call LinkDatabase
End If

Call TestorForceLinks 
.
.
.

Public Function TestLinks() As Boolean
  On Error GoTo Fout
  Dim Maakl As Boolean
  Dim Bel As String
  Dim tdf As TableDef
  Dim BackendPath As Variant
  Maakl = False
  TestLinks = False
  BackendPath = DLookup("[Database]", "MSysObjects", "Not IsNull(Database)")    'haal backendlocatie uit huidige links

  If IsNull(BackendPath) Then
    Maakl = True
    GoTo Verder2
  End If

  If BackendPath <> P_BackendPath Then
    Maakl = True
    GoTo Verder2
  End If

  For Each tdf In CurrentDb.TableDefs
    If (tdf.Attributes And dbAttachedTable) = dbAttachedTable Then
      Bel = Nz(DLookup("[Database]", "MSysObjects", "Foreignname=" & cq & tdf.Name & cq))
      If Bel <> P_BackendPath Then
        Maakl = True
        GoTo Verder1
      Else
        '   Application.SetHiddenAttribute acTable, tdf.Name, True
      End If
      'SysCmd acSysCmdSetStatus, "Test link table [" & tdf.name & "]..."
    End If
  Next tdf
Verder1:
  Set tdf = Nothing
Verder2:
  If Maakl Or P_ForceLink Then   'P_forcelink wordt aangezet bij updatebackend
    P_SkipMaakLink = False
    If RelinkTables(P_BackendPath) Then TestLinks = True
  Else
    P_SkipMaakLink = True
    TestLinks = True
  End If

Exit_fout:
  Exit Function
Fout:
  MsgBox Err.Description
  SysCmd acSysCmdClearStatus
End Function


Public Sub TestorForceLinks()
' kijk of er een fout optreed bij het maken van de link naar kpbini zoja dan force links
  On Error GoTo Forcelinks
  Dim rstest As New ADODB.Recordset
  Dim Getoond As Boolean
  Set rstest = New ADODB.Recordset
  rstest.Open "gebruikers", CurrentProject.Connection, adOpenKeyset, adLockOptimistic
  rstest.Close
  Set rstest = Nothing

  Exit Sub
Forcelinks:
  Call RemoveLinks
  Call LinkDatabase
End Sub


Public Sub RemoveLinks()
  On Error Resume Next    'negeer fouten
'http://www.dbforums.com/microsoft-access/997455-error-trying-relink-vba.html
  Dim tdf As TableDef
  For Each tdf In CurrentDb.TableDefs
    If Left(tdf.Name, 4) <> "MSys" And (tdf.Attributes And dbAttachedTable) = dbAttachedTable Then
      CurrentDb.TableDefs.Delete tdf.Name
    End If
  Next tdf
  Set tdf = Nothing
End Sub

Public Sub LinkDatabase()
'http://www.dbforums.com/microsoft-access/997455-error-trying-relink-vba.html
  On Error GoTo Fout
  Dim dbs As Database
  Dim tdf As TableDef
  Dim Getoond As Long
  Dim rs As New ADODB.Recordset
  Dim strDBPath As String
  strDBPath = P_BackendPath
  Set dbs = OpenDatabase(strDBPath, False, False, ";PWD=" & P_BackendPassWord)
  rs.Open "kpbinife", CurrentProject.Connection, adOpenKeyset, adLockOptimistic
  Getoond = rs.Fields("opgestart")

  If P_Runtime And Getoond > 0 Then
    MsgBox ("Attentie!" & vbCrLf & vbCrLf & _
            "De links naar de tabellen in de backend worden nu vernieuwd" & vbCrLf & vbCrLf & _
            "Voor gebruikers van het runtime pakket kunnen nu beveiligingswaarschuwingen volgen!" & vbCrLf & vbCrLf & _
            "Geef dan s.v.p. voor alle tabellen toestemming om te openen!" & vbCrLf & vbCrLf & _
            "N.b. Dit wordt maar eenmaal gevraagd en komt alleen weer voor bij verandering van de backend!")
    Getoond = Getoond + 1
    rs.Fields("opgestart") = Getoond
    rs.Update
    rs.Close
  Else
    rs.Close
  End If

  For Each tdf In dbs.TableDefs
    If Left(tdf.Name, 4) <> "MSys" Then
      DoCmd.TransferDatabase acLink, "Microsoft Access", Trim(strDBPath), acTable, tdf.Name, tdf.Name
      Application.SetHiddenAttribute acTable, tdf.Name, True
      SysCmd acSysCmdSetStatus, "Processing table [" & tdf.Name & "]..."
    End If
  Next tdf
  SysCmd acSysCmdClearStatus
  Set dbs = Nothing
  Set tdf = Nothing
Uit:
  Exit Sub
Fout:
  MsgBox "Linkdatabase : " & Err.Description
  DoCmd.Quit
End Sub


Public Function SelectBackend(PathNaam1 As String) As Boolean
  On Error GoTo Fout
  Dim fd As FileDialog
  Dim FileSpec As String
  Dim VrtSelectedItem As Variant
  SelectBackend = False
  Set fd = Application.FileDialog(msoFileDialogFilePicker)
  With fd
    .Filters.Clear
    .Filters.Add "Files *(.data) ", "*.data"
    .AllowMultiSelect = False
    .Title = "Zoek en selecteer de backend " & C_BeName
    .InitialFileName = CurDir
    .InitialView = msoFileDialogViewDetails
    If .Show = -1 Then
      For Each VrtSelectedItem In .SelectedItems
        If (InStr(VrtSelectedItem, Left(C_BeName, 4)) = 0) Or (InStr(Right(VrtSelectedItem, 4), "data") = 0) Then
          MsgBox "S.v.p. selecteer " & C_BeName & " of een back-upbestand hiervan!"
          SelectBackend = False
        Else
          PathNaam1 = VrtSelectedItem
          SelectBackend = True
        End If
      Next VrtSelectedItem
      'The user pressed Cancel.
    End If
  End With
  Set fd = Nothing
Uit:
  Exit Function
Fout:
  MsgBox Err.Description
End Function
Hopelijk heb je er wat aan
groet JanvP
 
Beste,
Bedankt voor de reactie. Ik zal er morgen naar kijken.

Groeten,
Timg
 
De methode van Perpon werkt op zich prima, aan de code mankeert niks, maar je hoeft in jouw geval niet van VBA gebruik te maken om de verschillende frontends aan dezelfde backend te koppelen. Omdat de lokatie wel verschilt voor de frontends, moet je eenmalig met de hand in het menu <Koppelingen> de databases koppelen aan de voor die frontend toepasselijke backend lokatie. Daarna kan elke frontend gewoon gebruikt worden. Voor het onderhoud van de diverse frontends maakt het verder ook niet zoveel meer uit: als je tabellen toevoegt of wijzigt moet je de koppelingen (handmatig of via VBA) bijwerken; nieuwe formulieren en rapporten etc. kun je gewoon importeren als vervanging van de bestaande.
 
Beste,

Dus ik kan de back-end op de netwerkschijf zetten en dan achteraf bij iedereen even langsgaan om de juiste koppeling te maken?
Dit zou wel een goede oplossing zijn denk ik.

Ik probeer de database te splitsen, maar ik krijg 2 foutmeldingen:
- Het subscript valt buiten het bereik
- Ongeldige procedure-aanroep of ongeldig argument

Het eerste heb ik opgezocht en het probleem zou kunnen liggen bij het gegevenstype.
Ik ben al mijn tabellen afgegaan, maar deze staan, naar mijn weten allemaal goed ingesteld...
Weet iemand waar het nog aan zou kunnen liggen?

Alvast bedankt,
Timg
 
Beste,

Pas als ik al mijn relaties verwijder kan ik de database splitsen.
Normaal zouden relaties toch geen probleem mogen zijn? of wel?

Alvast bedankt,
Timg
 
In de backend heb je normaal gesproken de relaties liggen. Als je de tabellen in de frontend gaat koppelen, zouden de relaties meegenomen moeten worden. Overigens maakt het niet zoveel uit als je ze in de frontend niet zou zien, want ze liggen er toch wel (in de backend).
 
Beste,

Ik heb alle relaties verwijdert, de database opgesplitst en in de back-end de relaties terug gemaakt. Ik krijg geen foutmeldingen. :thumb:

Als er verder nog problemen zouden optreden laat ik wel iets weten.

Nogmaals bedankt.

Groeten,
Timg
 
Beste,

Ik heb nog volgende vraag:
Ik heb nu 4 front-ends. in deze front-ends staan ook nog de tabellen met alle gegevens.
Deze kan ik wel verbergen zodat ze deze niet kunnen bekijken, maar gaat door de tabellen de omvang van de database ook niet zeer snel stijgen?

Zo ja, is er een mogelijkheid om het comprimeren van de database automatisch te laten uitvoeren?
Ik denk dat er geen enkele werknemer al gewerkt heeft met Access, dus gaan ze niet weten hoe dit te doen.

Alvast bedankt,
Timg
 
Beste,

Ik heb nog volgende vraag:
Ik heb nu 4 front-ends. in deze front-ends staan ook nog de tabellen met alle gegevens.
Deze kan ik wel verbergen zodat ze deze niet kunnen bekijken, maar gaat door de tabellen de omvang van de database ook niet zeer snel stijgen?

Zo ja, is er een mogelijkheid om het comprimeren van de database automatisch te laten uitvoeren?
Ik denk dat er geen enkele werknemer al gewerkt heeft met Access, dus gaan ze niet weten hoe dit te doen.

Alvast bedankt,
Timg

Lompe vraag, het comprimeren wordt in de back-end gedaan. :)
 
Timb,

Helemaal geen lompe vraag, maar een heel goede vraag. Je kan natuurlijk telkens aan de wandel om bij iedereen te comprimeren, wat natuurlijk erg collegiaal is.
Maar je kan ook de volgende een routine gebruiken :
.
Code:
Public Function Comprimeren() As Boolean
  On Error GoTo err_comprimeren
  Dim bak As String
  Dim Strbe2 As String
  Dim F1 As String
  Dim f2 As String
  Dim j As Integer
  Comprimeren = False

  j = AantalGebruikers(P_BackendPath)
  If j > 1 Then
    MsgBox (" Comprimeren is niet mogelijk bij meerdere gebruikers(" & j & ")")
    Exit Function
  End If

  Strbe2 = Trim(P_BackendPath)
  bak = Left(Strbe2, Len(Strbe2) - 4) & "tmp"

  If FileExists(bak) Then Kill bak
  DBEngine.CompactDatabase Strbe2, bak, , , ";PWD=" & P_BackendPassWord

  If Not FileExists(bak) Then
    MsgBox ("Fout bij comprimeren/herstellen van database. " & vbCrLf & _
            "Bij comprimeren mogen andere gebruikers de backend niet gebruiken!" & vbCrLf & _
            "Probeert u het later nog een keer!  ")
    DoCmd.Quit
    Exit Function
  End If

  If FileExists(Strbe2) Then
    Kill Strbe2
    DBEngine.CompactDatabase bak, Strbe2, , , ";PWD=" & P_BackendPassWord
    Comprimeren = True
    P_ToCompress = False

    F1 = P_CheckPath
    f2 = Left(P_CheckPath, Len(P_CheckPath) - 5) & "temp1"

    If FileExists(f2) Then Kill f2
    DBEngine.CompactDatabase F1, f2, , , ";PWD=" & P_CheckPassWord
    If FileExists(f2) And FileExists(F1) Then Kill F1
    DBEngine.CompactDatabase f2, F1, , , ";PWD=" & P_CheckPassWord
    If FileExists(f2) Then Kill f2
    Comprimeren = True
    P_ToCompress = False
  Else
    MsgBox ("Ernstige fout bij het comprimeren/herstellen van de backend." & vbCrLf & _
            "Door nog onbekende oorzaak (netwerkproblemen, meerdere gebruikers?) is de backendfile verloren gegaan. " & vbCrLf & _
            "Kopieer of hernoem in de backendmap " & vbCrLf & _
            Left(Strbe2, Len(Strbe2) - 9) & vbCrLf & _
            "de file pbbe.tmp naar pbbe.data" & vbCrLf & _
            "Komt dit probleem vaker voor, svp even contact opnemen ! " & vbCrLf & _
            "Het programma wordt nu gesloten")
    DoCmd.Quit
  End If
exit_comprimeren:
  Exit Function
err_comprimeren:
  MsgBox Err.Description
  MsgBox ("Fout bij comprimeren/herstellen van database. " & vbCrLf & _
          "Bij comprimeren mogen andere gebruikers het postboek niet gebruiken!" & vbCrLf & _
          "Probeert u het nog een keer! ")
  P_ToCompress = True
  Resume exit_comprimeren
End Function

met de volgende code kan je er ook voor zorgen dat de frontend wordt gecompirmeerd bij het afsluiten
Code:
    Application.SetOption ("Auto Compact"), 1

JanvP
Je moet er alleen voor zorgen dat de backend door niemand in gebruik is.
JanvP
 
Timb,

Helemaal geen lompe vraag, maar een heel goede vraag.
Je kan natuurlijk aan de wandel om bij iedereen te comprimeren, maar je kan ook de volgende routine gebruiken :
.
Code:
Public Function Comprimeren() As Boolean
  On Error GoTo err_comprimeren
  Dim bak As String
  Dim Strbe2 As String
  Dim F1 As String
  Dim f2 As String
  Dim j As Integer
  Comprimeren = False

  j = AantalGebruikers(P_BackendPath)
  If j > 1 Then
    MsgBox (" Comprimeren is niet mogelijk bij meerdere gebruikers(" & j & ")")
    Exit Function
  End If

  Strbe2 = Trim(P_BackendPath)
  bak = Left(Strbe2, Len(Strbe2) - 4) & "tmp"

  If FileExists(bak) Then Kill bak
  DBEngine.CompactDatabase Strbe2, bak, , , ";PWD=" & P_BackendPassWord

  If Not FileExists(bak) Then
    MsgBox ("Fout bij comprimeren/herstellen van database. " & vbCrLf & _
            "Bij comprimeren mogen andere gebruikers de backend niet gebruiken!" & vbCrLf & _
            "Probeert u het later nog een keer!  ")
    DoCmd.Quit
    Exit Function
  End If

  If FileExists(Strbe2) Then
    Kill Strbe2
    DBEngine.CompactDatabase bak, Strbe2, , , ";PWD=" & P_BackendPassWord
    Comprimeren = True
    P_ToCompress = False

    F1 = P_CheckPath
    f2 = Left(P_CheckPath, Len(P_CheckPath) - 5) & "temp1"

    If FileExists(f2) Then Kill f2
    DBEngine.CompactDatabase F1, f2, , , ";PWD=" & P_CheckPassWord
    If FileExists(f2) And FileExists(F1) Then Kill F1
    DBEngine.CompactDatabase f2, F1, , , ";PWD=" & P_CheckPassWord
    If FileExists(f2) Then Kill f2
    Comprimeren = True
    P_ToCompress = False
  Else
    MsgBox ("Ernstige fout bij het comprimeren/herstellen van de backend." & vbCrLf & _
            "Door nog onbekende oorzaak (netwerkproblemen, meerdere gebruikers?) is de backendfile verloren gegaan. " & vbCrLf & _
            "Kopieer of hernoem in de backendmap " & vbCrLf & _
            Left(Strbe2, Len(Strbe2) - 9) & vbCrLf & _
            "de file pbbe.tmp naar pbbe.data" & vbCrLf & _
            "Komt dit probleem vaker voor, svp even contact opnemen ! " & vbCrLf & _
            "Het programma wordt nu gesloten")
    DoCmd.Quit
  End If
exit_comprimeren:
  Exit Function
err_comprimeren:
  MsgBox Err.Description
  MsgBox ("Fout bij comprimeren/herstellen van database. " & vbCrLf & _
          "Bij comprimeren mogen andere gebruikers het postboek niet gebruiken!" & vbCrLf & _
          "Probeert u het nog een keer! ")
  P_ToCompress = True
  Resume exit_comprimeren
End Function
met de volgende code kan je er ook voor zorgen dat de frontend wordt gecompirmeerd bij het afsluiten
Code:
    Application.SetOption ("Auto Compact"), 1
Zorg er wel voor dat de backend door niemand in gebruik is voordat je comprimeert
JanvP
 
Hey Perpon,

Als ik volgende code gebruik:
Code:
Application.SetOption ("Auto Compact"), 1

Ik zet deze bij mijn knop afsluiten en net boven de regel: docmd.Quit.
Dit werkt, maar de werknemers kunnen niet weten of er iemand bezig is op de back-end of op een andere front-end. Kan dit serieuze problemen met zich meegeven wanneer dit wel zou gebeuren?

Normaal moet er niemand op de back-end komen, bij aanvullen op de back-end gebeurt via de formulieren in de front-end.

Alvast bedankt,
Timg
 
Ik zou het eerlijk gezegd helemaal niet via VBA doen, maar zelf als admin om de zoveel tijd. Er is weinig reden om elke keer bij afsluiten de db te comprimeren. Als je het een keer per week in de backend doet, is dat meer dan genoeg. Desnoods kun je dat schedulen met een Scheduled Task, zodat het comprimeren 's nachts gebeurt.
 
Timb
Bij het opstarten van de frontend kan je een tellertje laten lopen , zodat bij afsluiten bijvoorbeeld pas na 5 keer wordt gecomprimeerd. Hoe vaak er moet worden gecomprimeerd kan het beste in de praktijk worden bepaald. Misschien is comprimeren na 20 keer prima.
Code:
Private Afsluiten_knop133_Click()
  Dim i As Long
  Dim h, sql
  Dim rs As New ADODB.Recordset
  On Error GoTo Fout
  If FoutTest Then DoCmd.Quit
  Call SluitForms(" ")
  Application.SetOption ("Auto Compact"), 0
  rs.Open "kpbiniFE", CurrentProject.Connection, adOpenKeyset, adLockOptimistic
  i = Nz(rs.Fields("xopgestart"), 0)

  
  If AantalGebruikers(P_BackendPath) > 1 Then
    DoCmd.Quit
  Else
    If i > 5 Then
      Application.SetOption ("Auto Compact"), 1
      rs.Fields("xopgestart") = 0
      rs.Update
      rs.Close
      h = SysCmd(acSysCmdSetStatus, "Comprimeren!")
      If Comprimeren Then h = SysCmd(acSysCmdSetStatus, "Comprimeren done")
      DoCmd.Quit
    Else
      DoCmd.Quit
    End If
  End If

Uit2:
  Exit Sub
Fout:
  MsgBox Err.Number & " - " & Err.Description
  DoCmd.Quit
  GoTo Uit2
End Sub
Met de routine aantalgebruikers kan je het aantal gebruikers bepalen.
Code:
Public Function AantalGebruikers(BackendPath As String) As Integer    ' Geeft het aantal gebruikers van de backend weer
  On Error GoTo Fout
  Dim cn As New ADODB.Connection
  Dim rs As ADODB.Recordset
  Dim fldPc As ADODB.Field
  Dim fldUser As ADODB.Field
  Dim strItem As String
  Dim gC1 As Integer
  Dim sG As String
  gC1 = 0
 
  Const JET_SCHEMA_USERROSTER As String = "{947bb102-5d43-11d1-bdbf-00c04fb92675}"
  With cn
    .Provider = "Microsoft.ACE.OLEDB.12.0"
    .Properties("Data Source") = BackendPath
    .Properties("Jet OleDB:Database Password") = P_BackendPassWord
    .Open
  End With
  Dim l, users, i, pcnaam0, pcnaam1, usernaam0, usernaam1
  Set rs = cn.OpenSchema(adSchemaProviderSpecific, , JET_SCHEMA_USERROSTER)
  rs.MoveFirst
  '  MsgBox rs.RecordCount

  Do Until rs.EOF
    Set fldPc = rs.Fields(0)
    Set fldUser = rs.Fields(1)
    pcnaam0 = fldPc.Value
    usernaam0 = fldUser.Value
    gC1 = gC1 + 1
    sG = sG & gC1 & ":" & pcnaam0 & " -  " & usernaam0 & vbCrLf
    If Len(Trim(Nz(pcnaam0))) = 0 And Len(Trim(Nz(usernaam0))) = 0 Then
      MsgBox "Kan de pc- en/of gebruikersnaam bij backend niet bepalen." & vbCrLf & _
             "Verplaats s.v.p. de backend naar een server of naar een public map op een pc "
      AantalGebruikers = 99
      If Not P_Developer Then
        DoCmd.Quit
      Else
        GoTo Einde
      End If

    End If
    rs.MoveNext
    If Not rs.EOF Then
      Set fldPc = rs.Fields(0)
      Set fldUser = rs.Fields(1)
      pcnaam1 = fldPc.Value
      usernaam1 = fldUser.Value
      gC1 = gC1 + 1
      sG = sG & gC1 & ":" & pcnaam1 & " -  " & usernaam1 & vbCrLf
    End If
    If pcnaam0 = pcnaam1 And usernaam0 = usernaam1 Then gC1 = gC1 - 1
    pcnaam1 = pcnaam0
    usernaam1 = usernaam0
  Loop

  Set rs = Nothing
  Set cn = Nothing
  Set fldPc = Nothing
  Set fldUser = Nothing
  AantalGebruikers = gC1
  'MsgBox sG & vbCrLf & "Aantal gebruikers: gC1 : " & gC1 & " of gC2 : " & gC2 & vbCrLf & sG & vbCrLf & vbCrLf & " Roster=" & HRoster
Einde:
  Exit Function
Fout:
  MsgBox Err.Description & vbCrLf & "Fout in routine aantalgebruikers, het programma wordt afgesloten"
  cn.Close
  Set cn = Nothing
  Set rs = Nothing
  AantalGebruikers = 99
  If Not P_Developer Then DoCmd.Quit
End Function

De routine aantalgebruikers moet je pas aanroepen wanneer alle formulieren welke zijn gekoppeld aan een backendtabel gesloten zijn, vandaar de volgende routine
Code:
Public Sub SluitForms(uitzondering As String)
  Dim i As Integer, h As String

  On Error Resume Next
  For i = 0 To Forms.Count - 1
    h = Forms(i).Name
    If h = "hoofdmenu" Or h = uitzondering Then
      'skip
    Else
      DoCmd.Close acForm, h, acSaveYes
    End If
  Next

End Sub

Wellicht kan je er wat mee.

Groet JanvP
 
Waarom zo moeilijk. In menu "Extra" --> "Opties" tabblad "Algemeen" kun je de optie "Comprimeren bij sluiten" aanvinken. Zowel in de Back- als Frontend. Zodra de laatste gebruiker de database sluit wordt deze gecomprimeerd.
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan