2009-09-08 8 views
1

Je crée un programme de nomenclatures. Il existe deux tables principales nommées Products et Sub_Products. Dans le tableau Products, les champs sont (Product_Name, Code). Dans le tableau Sub_Products, les champs sont (Code, Sub_Name).Répétition d'une requête pour produire un rapport

Les tables sont liées avec le code, i.e. .: un product est composé de plusieurs sub_product s, chaque sub_product est un aussi bien product, ce qui en fait ont beaucoup sub_product s. J'ai créé une requête qui lit un product et obtient le sub_product J'ai besoin d'une requête pour comparer Sub_Name avec Product_Name et puis vérifier plus sub_product s, continue jusqu'à ce que plus aucun sub_product s sont trouvés.

Des idées?

+0

"Bill of Materials" devrait être "Nomenclatures" :-P –

+0

respectueusement, Flanagan, vous @ Andrew tort. Une "nomenclature" est une liste des composants d'un objet traité comme une unité. C'est une "facture" des "matériaux" utilisés pour construire l'objet composé. C'est un terme commun dans le domaine de la fabrication, et donc, dans les bases de données qui stockent des informations sur l'inventaire. –

Répondre

1

Je suppose que vous devrez utiliser un script plutôt que la requête SQL pour les parcourir. En supposant que les produits peuvent être imbriqués plus de 3 niveaux.

0

J'ai travaillé sur ce problème exact dans une application ASP.NET MVC. Une fonction regroupant tous les sous-produits pour chaque produit et récursif sur chaque sous-produit a bien fonctionné. Nous avons des nomenclatures de 15 niveaux de profondeur.

0

Je réalise que cette question a été posée il y a longtemps, mais j'avais une question très similaire et j'ai finalement trouvé une bonne réponse. Donc, je l'affiche ici au cas où quelqu'un doit savoir comment créer une nomenclature.

Dans mon exemple, il existe une table appelée "Part_Item_Table" qui répertorie les éléments parents et tous leurs childeren. Ces enfants peuvent aussi être parents d'autres enfants. La difficulté était que la nomenclature pouvait avoir 3 niveaux de profondeur jusqu'à 30 niveaux de profondeur ou plus. Mon "Part_Item_Table" indique également si les éléments sont des éléments "Make" ou non. Seuls les objets "Make" auront childeren. La table que vous interrogez n'a peut-être pas cette fonctionnalité, mais le code ci-dessous sera probablement toujours utile pour obtenir l'idée. Cet ensemble de code utilise plusieurs choses qui m'étaient inconnues, comme le code récursif, l'appel d'une requête que j'avais déjà créée et la transmission d'une variable à l'aide des méthodes querydef, et l'utilisation de jeux d'informations pour obtenir de grands ensembles d'informations. les fonctions. J'ai également utilisé un champ de séquence dans ma table de nomenclature afin que je puisse le trier et voir la nomenclature dans l'ordre dans lequel il est censé être (Montrer visuellement quels éléments de niveau 3 sont regroupés en éléments de niveau 2). S'il y a quelque chose qui peut être amélioré, je suis ouvert aux suggestions. Cela fonctionne pour mes besoins en ce moment et j'espère que c'est utile à quelqu'un d'autre.

Option Compare Database 

Public stFirstPart As String 
Private Const BOMTable As String = "BOM_Table" 'Set this variable to the name of the table 
Private Const ComponentQ As String = "GetComponentsQ" 'Set to the name of the query in the database 

Function BOM() 
Dim stQuery As String 'Used to make a query 
Dim i As Integer  'Used to create the sequence number 
Dim iLevel As Integer 'Used to show BOM level 
Dim rsParent, rsBOMTable As DAO.Recordset  'Used to hold query results 

'Make sure there is a part number in the form 
If IsNull(Forms![Entry Form]![Part_Number]) Then 
    Debug.Print "There is no part number entered in the form" 
    MsgBox "There is no part number in the form.", vbOKOnly, "Can't fool me." 
    Exit Function 
End If 

stFirstPart = Forms![Entry Form]![Part_Number] 'Get the top part number from the form 

'Make sure this is a Make item. Only make items will have childeren 
stQuery = "SELECT ITEM.ITEM_NO, ITEM.MAKE_BUY_FLAG, ITEM.CURRENT_FLAG " & _ 
     " FROM PART_ITEM_TABLE AS ITEM " & _ 
     " WHERE (((ITEM.ITEM_NO)='" & stFirstPart & "') AND ((ITEM.MAKE_BUY_FLAG)='M') AND ((ITEM.CURRENT_FLAG)='Y'));" 

Set rsParent = CurrentDb.OpenRecordset(stQuery) 

If rsParent.EOF And rsParent.BOF Then 
    Debug.Print "This is not a make item" 
    MsgBox "This is not a Make item.", vbOKOnly, "I tried." 
    Exit Function 
End If 

'Clear the BOM table and load this first part number 
DoCmd.SetWarnings False 

DoCmd.RunSQL "Delete from " & BOMTable & "" 
Set rsBOMTable = CurrentDb.OpenRecordset(BOMTable, dbOpenDynaset) 

i = 1 
iLevel = 1 

rsParent.MoveFirst 
With rsBOMTable 
    .AddNew 
    !Sequence = i 
    !Level = iLevel 
    !Item_Number = stFirstPart 
    !Make_Buy = "M" 
    .Update 
End With 

rsParent.Close 
Set rsParent = Nothing 
rsBOMTable.Close 
Set rsBOMTable = Nothing 

    '----------------------------------------------------------------------------------------------------------------------------------- 
    'Start going down levels 
    '----------------------------------------------------------------------------------------------------------------------------------- 
iLevel = 2 
Call RecursiveLevels(stFirstPart, iLevel, i) 

DoCmd.SetWarnings True 
End Function 

Function RecursiveLevels(PartNumber As String, iLevel As Integer, i As Integer) 
Dim rsLevels As DAO.Recordset 
Dim stPart As String 

Set rsLevels = GetComponents(PartNumber) 

If rsLevels.BOF And rsLevels.EOF Then 
    Debug.Print "This was a Make item with no children. That shouldn't happen. "; PartNumber 
    GoTo ExitPoint 
End If 

rsLevels.MoveFirst 
Do While Not rsLevels.EOF 
    If rsLevels!Make_Buy <> "M" Then ' Anything that is not a Make item is written to the BOM table one line at a time. 
     i = i + 1 
     Call WriteToBOMTable(iLevel, i, rsLevels!Parent_Number, rsLevels!Component_Number, rsLevels!Make_Buy) 

    Else 'The Make item is written to the table, then we query for all of its children 
     stPart = rsLevels!Component_Number 
     i = i + 1 

     Call WriteToBOMTable(iLevel, i, rsLevels!Parent_Number, rsLevels!Component_Number, rsLevels!Make_Buy) 

     If stPart = stFirstPart Then 'Check to make sure this recursive thing doesn't go on forever. 
      Debug.Print "This part number is the same as the first part number. Circ Reference. "; stPart 
      GoTo ExitPoint 
     End If 

     iLevel = iLevel + 1  ' get ready to go one level deeper 
     Call RecursiveLevels(stPart, iLevel, i) 

    End If 
rsLevels.MoveNext 
Loop 

ExitPoint: 
iLevel = iLevel - 1  'Done with this level. Come back up a level. 
rsLevels.Close 
Set rsLevels = Nothing 
End Function 

Function WriteToBOMTable(Level As Integer, i As Integer, ParentNumber As String, ComponentNumber As String, MakeBuy As String) 
Dim rsBOMTable As DAO.Recordset 

Set rsBOMTable = CurrentDb.OpenRecordset(BOMTable, dbOpenDynaset) 

With rsBOMTable 
.AddNew 
!Parent_Number = ParentNumber 
!Item_Number = ComponentNumber 
!Level = Level 
!Make_Buy = MakeBuy 
!Sequence = i 
.Update 
End With 

Debug.Print "Level: "; Level; "Component: "; ComponentNumber 

rsBOMTable.Close 
Set rsBOMTable = Nothing 

End Function 

Function GetComponents(PartNumber As String) As DAO.Recordset 
Dim qdf As QueryDef 

Set qdf = CurrentDb.QueryDefs(ComponentQ) 
qdf.Parameters("PartNumber") = PartNumber 
Set GetComponents = qdf.OpenRecordset 

End Function