Question calculate inbreeding (1 Viewer)

MajP

You've got your good things, and you've got mine.
Local time
Yesterday, 20:05
Joined
May 21, 2018
Messages
8,525
This working with 2097, 1 (4) of the first Glosters we got. At the moment only working on children, grand children and great grand children. She has 99 off spring.
If that is something you want to do, you have all the pieces to build the queries and export to Excel. You could pretty easily automate all of that. Or do not export, but have the way to display that within the database. Currently you have Tbl_Pedigree what gives you half the information (parents, grand parents...), tbl_birds gives you siblings. I would just make Tbl_Offspring doing the recursion. That would have to get updated more often. You do not get more ancestors as time goes on, but you do get more offspring. Then you could pick any bird and and return those queries/worksheets.
 

InFlight

User
Local time
Today, 12:05
Joined
Jun 11, 2015
Messages
130
Would it be very hard to add your tree control. Still working on a couple of problems. One is when i add a new egg when the pair don't have any, i get no current record error.
 

MajP

You've got your good things, and you've got mine.
Local time
Yesterday, 20:05
Joined
May 21, 2018
Messages
8,525
Adding the tree view is easy. Just have to import a few forms and modules. The no current record is because there is nothing in the subform but there is some code referencing a control or field. I will look when I get a chance
 

InFlight

User
Local time
Today, 12:05
Joined
Jun 11, 2015
Messages
130
The no current record is because there is nothing in the subform but there is some code referencing a control or field. I will look when I get a chance
I Have sorted it. I was doing a rst.MoveLast with no records:rolleyes:
 

MajP

You've got your good things, and you've got mine.
Local time
Yesterday, 20:05
Joined
May 21, 2018
Messages
8,525
I will send you an update with the treeview demo tonight. When developing an Access db it is always a good idea to routinely import all your objects into a new clean DB. This avoids bloat and corruption. If you want to use the treeview you could use this db as the start. It is a clean db with the objects imported into it. If you have updated tables and forms you can import your objects into this one and delete the ones I have. The other way would be for you to create a new db and import the most current objects from both dbs.

I added an important module called mdlOffspring. This is another recursive call to build an offspring table. It has every bird and all of its offspring. With that build you could completely automate that Excel file that you show.

In this case after updating new birds you have to run UpdateAllOffSpring
Code:
Public Sub UpdateAllOffSpring()
  Dim rsBirdLoop As DAO.Recordset
  Set rsBirdLoop = CurrentDb.OpenRecordset("tbl_Birds", dbOpenDynaset)
  Do Until rsBirdLoop.EOF
    AddUpdateOffSpring rsBirdLoop!ID
    rsBirdLoop.MoveNext
  Loop
End Sub
Public Sub AddUpdateOffSpring(BirdID As Long)
  Dim rsBird As DAO.Recordset
  DeleteOffSpring BirdID
  Set rsBird = CurrentDb.OpenRecordset("tbl_Birds", dbOpenDynaset)
  AddRecursiveMaleParent rsBird, BirdID, GetRingNo(BirdID), 2
  AddRecursiveFemaleParent rsBird, BirdID, GetRingNo(BirdID), 2
End Sub
Public Sub DeleteOffSpring(ByVal BirdID As Long)
    Dim strSql As String
    strSql = "Delete * FROM tbl_OffSpring where BirdID = " & BirdID
    CurrentDb.Execute strSql
End Sub

Private Sub AddRecursiveMaleParent(rsBird As DAO.Recordset, StartingBirdID As Long, ByVal FatherRing As String, Generation As Long)
  'This is a confusing name.  Not adding the Father node but adding a child who has this bird as the father
  On Error GoTo errLable
  Dim strCriteria As String
  Dim bk As String
  Dim BirdID As Long
  Dim BirdRingNo As String
  Dim strSql As String
  strCriteria = "FatherID = '" & FatherRing & "'"
  rsBird.FindFirst strCriteria
  'Debug.Print strCriteria
  Do Until rsBird.NoMatch
   ' Debug.Print "match"
    BirdID = rsBird.Fields("ID")
    BirdRingNo = rsBird.Fields("RingNo")
    bk = rsBird.Bookmark
    
    strSql = "Insert INTO tbl_OffSpring (BirdID, OffSpringID, Generation ) VALUES (" & StartingBirdID & ", " & BirdID & ", " & Generation & ")"
    'Debug.Print strSql
    CurrentDb.Execute strSql
 
    Call AddRecursiveMaleParent(rsBird, StartingBirdID, BirdRingNo, Generation + 1)
   rsBird.Bookmark = bk
   rsBird.FindNext strCriteria
  Loop
 Exit Sub
errLable:
  MsgBox Err.Number & " " & Err.Description & " In addrecursiveMaleParent"
  If MsgBox("Do you want to exit the loop?", vbYesNo, "Error In Loop") = vbYes Then
     Exit Sub
   Else
     Resume Next
   End If
End Sub
Private Sub AddRecursiveFemaleParent(rsBird As DAO.Recordset, StartingBirdID As Long, ByVal MotherRing As String, Generation As Long)
  'This is a confusing name.  Not adding the Mother node but adding a child who has this bird as the Mother
  On Error GoTo errLable
  Dim strCriteria As String
  Dim bk As String
  Dim BirdID As Long
  Dim BirdRingNo As String
  Dim strSql As String
  strCriteria = "MotherID = '" & MotherRing & "'"
  rsBird.FindFirst strCriteria
  'Debug.Print strCriteria
  Do Until rsBird.NoMatch
    Debug.Print "match"
    BirdID = rsBird.Fields("ID")
    BirdRingNo = rsBird.Fields("RingNo")
    bk = rsBird.Bookmark
    
    strSql = "Insert INTO tbl_OffSpring (BirdID, OffSpringID, Generation ) VALUES (" & StartingBirdID & ", " & BirdID & ", " & Generation & ")"
    'Debug.Print strSql
    CurrentDb.Execute strSql
 
    Call AddRecursiveFemaleParent(rsBird, StartingBirdID, BirdRingNo, Generation + 1)
   rsBird.Bookmark = bk
   rsBird.FindNext strCriteria
  Loop
 Exit Sub
errLable:
  MsgBox Err.Number & " " & Err.Description & " In addrecursiveFemaleParent"
  If MsgBox("Do you want to exit the loop?", vbYesNo, "Error In Loop") = vbYes Then
     Exit Sub
   Else
     Resume Next
   End If
End Sub

Example for 2097
Code:
RingNo	Offspring RingNo	GenerationName
2097 KG	4602	Child
2097 KG	4936	Child
2097 KG	4937	Child
2097 KG	5182	Child
2097 KG	5185	Child
2097 KG	5187	Child
2097 KG	7469	Child
2097 KG	4601	Child
2097 KG	4603	Child
2097 KG	4604	Child
2097 KG	4938	Child
2097 KG	5186	Child
2097 KG	7470	Child
2097 KG	7452	Child
2097 KG	1615	Grand Child
2097 KG	4917	Grand Child
2097 KG	7444	Grand Child
2097 KG	7456	Grand Child
2097 KG	7457	Grand Child
2097 KG	4918	Grand Child
2097 KG	7459	Grand Child
2097 KG	1613	Grand Child
2097 KG	7458	Grand Child
2097 KG	1510	Grand Child
2097 KG	7442	Grand Child
2097 KG	7441	Grand Child
2097 KG	5701	Grand Child
2097 KG	4921	Grand Child
2097 KG	4919	Grand Child
2097 KG	1612	Grand Child
2097 KG	7443	Grand Child
2097 KG	5702	Grand Child
2097 KG	1611	Grand Child
2097 KG	1616	Grand Child
2097 KG	4920	Grand Child
2097 KG	1614	Grand Child
2097 KG	3705	Grand Child
2097 KG	4933	Great Grand Child
2097 KG	4925	Great Grand Child
2097 KG	4931	Great Grand Child
2097 KG	4930	Great Grand Child
2097 KG	4923	Great Grand Child
2097 KG	4922	Great Grand Child
2097 KG	4924	Great Grand Child
2097 KG	4927	Great Grand Child
2097 KG	4915	Great Grand Child
2097 KG	4932	Great Grand Child
2097 KG	4925-H	Great Grand Child
2097 KG	1502	Great Great Grand Child
2097 KG	1503	Great Great Grand Child
2097 KG	1501	Great Great Grand Child
2097 KG	3730	Great Great Grand Child

I also added another function to return the common ancestors for two birds and put this as a demo on the partnership form. So for example
4925 and 1514
Code:
4925
 Ancestor: 2273 KG Relation: Great Grand Parent ****
 Ancestor: 2273 KG Relation: Great Grand Parent ****
 Ancestor: 2097 KG Relation: Great Grand Parent Hen
 Ancestor: 2097 KG Relation: Great Grand Parent Hen
1514
 Ancestor: 2273 KG Relation: Great Grand Parent ****
 Ancestor: 2097 KG Relation: Great Grand Parent Hen
 Ancestor: 2097 KG Relation: Great Grand Parent Hen
(Note: The duplication is correct since the birds appear multiple times in the lineage)

Code:
Public Function GetCommonAncestors(bird1ID As Long, bird2ID As Long)
  Dim strSql As String
  Dim rs As DAO.Recordset
  Dim strOut As String
  strSql = "Select * from qry_common_Ancestors where birdID = " & bird1ID & " and AncestorID in (Select AncestorID from tbl_Pedigree where BirdID = " & bird2ID & ")"
  strSql = strSql & " ORDER BY Generation, Gender"
  'Debug.Print strSql
  Set rs = CurrentDb.OpenRecordset(strSql)
  If Not rs.EOF Then
    strOut = rs!RingNo & vbCrLf
  Else
    Exit Function
  End If
  Do While Not rs.EOF
    strOut = strOut & " Ancestor: " & rs![Ancestor Ring] & " Relation: " & rs!GenerationName & " " & rs!gender & vbCrLf
    rs.MoveNext
  Loop
  strSql = "Select * from qry_common_Ancestors where birdID = " & bird2ID & " and AncestorID in (Select AncestorID from tbl_Pedigree where BirdID = " & bird1ID & ")"
  strSql = strSql & " ORDER BY Generation, Gender"
  Set rs = CurrentDb.OpenRecordset(strSql)
  strOut = strOut & rs!RingNo & vbCrLf
  Do While Not rs.EOF
    strOut = strOut & " Ancestor: " & rs![Ancestor Ring] & " Relation: " & rs!GenerationName & " " & rs!gender & vbCrLf
    rs.MoveNext
  Loop
  
  GetCommonAncestors = strOut
End Function
 

InFlight

User
Local time
Today, 12:05
Joined
Jun 11, 2015
Messages
130
I have been doing work on it, but just mainly tidy up code etc. I only did it in Excel to start to find out how much work their is.
I will use your DB and import mine. Thanks.
 

InFlight

User
Local time
Today, 12:05
Joined
Jun 11, 2015
Messages
130
Code:
Private Sub cmd_Details_Click()
    On Error GoTo cmd_Details_Click_Error

    Dim rs As DAO.Recordset
    Dim strSQL As String
    
    If Not IsNull(Me.RingNo) Then
        If DCount("[f_Variable]", "tblsys", "[f_Variable] = 'LastRingNumber'") = 0 Then
            strSQL = "Insert INTO tblSys (f_Variable, f_Value, f_Description, f_Season, f_Pair, f_cage, f_Record, f_Check)"
            strSQL = strSQL & " VALUES (" & Chr(34) & "LastRingNumber" & Chr(34) & ", " & Chr(34) & Me.RingNo & Chr(34) & ", " & Chr(34) & "Last RingNumber, for form " & Me.Name & Chr(34) & ", " & Me.Season & ", " & Me.PairID & ""
            strSQL = strSQL & ", " & Chr(34) & Me.CageID & Chr(34) & ", " & Me.CurrentRecord & ", " & Chr(34) & "None" & Chr(34) & ")"
            Debug.Print strSQL
            CurrentDb.Execute strSQL
        Else
            strSQL = "Update tblSys Set f_Value = " & q & Me.RingNo & q & _
                ", f_season = " & Me.Season & ", f_pair = " & Me.PairID & _
                ", f_Cage = " & q & Me.CageID & q & ", f_Record = " & _
                Me.CurrentRecord & ", f_Check = " & q & "None" & q & _
                " WHERE f_Variable = 'LastRingNumber'"
            CurrentDb.Execute strSQL
        End If
    DoCmd.OpenForm "frm_3_AllBirds"
    
    Exit Sub
    
    
    
 ' -----------------------------Changed to code above--------------------------------------------


        Set rs = CurrentDb().OpenRecordset("tblSys", dbOpenDynaset)
        With rs
            .FindFirst "[f_Variable] = 'LastRingNumber'"
            If .NoMatch Then
                .AddNew        'Create the entry if not found.
                ![f_Variable] = "LastRingNumber"
                ![f_Value] = Me.RingNo
                ![f_Description] = "Last RingNumber, for form " & Me.Name
                ![f_season] = Me.Season
                ![f_Pair] = Me.PairID
                ![f_Cage] = Me.CageID
                ![f_Record] = Me.CurrentRecord
                ![f_check] = "None"
                .Update
            Else
                .Edit          'Save the current record's primary key.
                ![f_Value] = Me.RingNo
                ![f_season] = Me.Season
                ![f_Pair] = Me.PairID
                ![f_Cage] = Me.CageID
                ![f_Record] = Me.CurrentRecord
                ![f_check] = "None"
                .Update
            End If
        End With
        rs.Close
    End If

    
    On Error GoTo 0
    Exit Sub

cmd_Details_Click_Error:

    MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure cmd_Details_Click, line " & Erl & "."

End Sub

Which is correct or better. The .AddNew seems easier.
 

MajP

You've got your good things, and you've got mine.
Local time
Yesterday, 20:05
Joined
May 21, 2018
Messages
8,525
I think it is the same. No real difference in this case.

You can shorten your code

Code:
            strSQL = strSQL & " VALUES (" & Chr(34) & "LastRingNumber" & Chr(34) & ", " & Chr(34) & Me.RingNo & Chr(34) & ", " & Chr(34) & "Last RingNumber, for form " & Me.Name & Chr(34) & ", " & Me.Season & ", " & Me.PairID & ""
            strSQL = strSQL & ", " & Chr(34) & Me.CageID & Chr(34) & ", " & Me.CurrentRecord & ", " & Chr(34) & "None" & Chr(34) & ")"
to
Code:
strSQL = strSQL & " VALUES ('LastRingNumber', '" & Me.RingNo & "', '" & "Last RingNumber, for form " & Me.Name & "", " & Me.Season & ", " & Me.PairID 
strSQL = strSQL & ", '" & Me.CageID "', " & Me.CurrentRecord & ", 'None')"
 

Users who are viewing this thread

Top Bottom