2010-07-06 6 views
4

J'ai une table dans une base MySQL comme ceci:données Format mysql dans Excel

+-------+--------+-------------+ 
| child | parent | data  | 
+-------+--------+-------------+ 
|  1 |  0 | house  | 
|  2 |  0 | car   | 
|  3 |  1 | door  | 
|  4 |  2 | door  | 
|  5 |  2 | windscreen | 
| 11 |  5 | wiper  | 
+-------+--------+-------------+ 

Je me suis connecté à mysql à partir d'Excel 2007 selon this tutoriel, sauf que j'ai créé les dns dans le système dns pas utilisateur dns, que travaillé pour moi.

J'ai un peu de connaissances sur les formules et je ne pouvais pas comprendre comment obtenir ces données sous forme de tableau:

house | door 
house | wall 
car | door 
car | windscreen | wiper 

Modifier 1

La partie MySQL est pas un problème ici. Cette table mysql pourrait très bien être une table excel.

Edit 2

Maintenant, je me rends compte qu'il n'a même pas été nécessaire de dire qu'il ya une table mysql ici juste un tableau Excel. Mais cela peut inspirer/aider quelqu'un.

Edit 3

Après quelques documents i ont réussi à résoudre les aspects les plus importants de mon problème

La gamme en tôle db:

child parent  data 
1  0   car 
2  0   house 
3  1   door 
4  2   door 
5  1   window 
6  2   window 
7  1   windscreen 
8  7   wiper 
9  4   color 
10  2   color 

J'ai un db nom qui fait référence à

=db!$A$2:OFFSET(db!$C$2,COUNTA(db!$C:$C)-2,0) 

un nom enfant

=db!$A$2:OFFSET(db!$A$2,COUNTA(db!$A:$A)-2,0) 

Dans une autre feuille avec la construction de nom j'ai commencé à partir de B2 et utilisé la formule suivante:

=IFERROR(
    IF(ISBLANK(B1), 
     LARGE(child,COUNTA($A$2:A$2)+1), 
     VLOOKUP(B1,db,2,0) 
    ),".") 

Dans une troisième feuille de sortie du nom que j'ai commencé de A1 et utilisé la formule:

=IFERROR(VLOOKUP(construct!B2,db,3,0),".") 

Maintenant, le dernier défi est de rendre les formules de construction et de sortie à dépenser automatiquement lorsque de nouvelles entrées sont ajoutées à la table principale, mais je ne pense pas que ce soit possible.

Modifier 4

Lors de l'importation de sql dans la feuille db il y aura une table au lieu de la plage de sorte que les formules vont chercher un peu différent. Cliquez dans la table, cliquez sur l'onglet de conception et de renommer la base de la table, puis dans la feuille de construction du début b2 avec cette formule:

=IFERROR(
    IF(ISBLANK(B1), 
    LARGE(INDIRECT("base[child]"),COUNTA($A$2:A$2)+1), 
    VLOOKUP(B1,base,2,0) 
),".") 
+0

Quelle est la profondeur maximale d'un arbre? Vous ne pouvez pas le faire avec une seule requête si la profondeur est illimitée. – Naktibalda

+0

Quelqu'un avec assez de rep devrait changer le titre et les balises pour refléter que ce poste est en fait une question sur l'affichage d'une table de données comme une hiérarchie ou un arbre. – technomalogical

Répondre

0

Tout d'abord, vous devez absolument utiliser cette connexion afin d'obtenir la des données à Excel? Parce que ce serait tellement plus simple si vous venez d'exporter les données elles-mêmes dans un fichier .csv qui peut ensuite être ouvert directement avec Excel.

Donnez un coup de feu: SELECT * FROM ... INTO OUTFILE '/temp.csv' FIELDS ESCAPED BY '""' TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\r\n';

En ce qui concerne votre question, il semble que vous essayez de mapper un arbre. Consultez les sites suivants:

  1. Trees in SQL databases
  2. Tree hierarchy in SQL
  3. SQL graph algorithms
+0

Merci pour vos réponses. En fait, cet ensemble de résultats est à partir de deux tables utilisant quelque chose comme ... DE données INNER JOIN arbre ON (data.id = tree.id), la partie avec mysql n'est pas vraiment un problème ici. En jouant récemment avec Excel, j'ai trouvé qu'il serait utile de tester ma base de données dans une feuille de calcul lorsque de nouvelles entrées sont ajoutées. Pour l'instant j'ai un script PHP où je teste ma structure de base de données mais je pense qu'il est temps d'essayer de nouvelles thigs. – Alqin

2

Voici comment je le ferais en utilisant VBA: d'abord créer un module de classe et nommez-CDatum. Mettez ce code là-dedans.

Option Explicit 

Private msID As String 
Private msData As String 
Private msParentID As String 


Public Property Get ID() As String 

    ID = msID 

End Property 

Public Property Let ID(ByVal sID As String) 

    msID = sID 

End Property 

Public Property Get Data() As String 

    Data = msData 

End Property 

Public Property Let Data(ByVal sData As String) 

    msData = sData 

End Property 

Public Property Get ParentID() As String 

    ParentID = msParentID 

End Property 

Public Property Let ParentID(ByVal sParentID As String) 

    msParentID = sParentID 

End Property 

Public Property Get ChildCount() As Long 

    Dim i As Long 
    Dim lReturn As Long 

    For i = 1 To gclsData.Count 
     If gclsData.Data(i).ParentID = Me.ID Then 
      lReturn = lReturn + 1 
     End If 
    Next i 

    ChildCount = lReturn 

End Property 

Public Property Get Tree() As Variant 

    Dim vaReturn As Variant 
    Dim vaChild As Variant 
    Dim i As Long, j As Long 
    Dim lChildCount As Long 
    Dim lRowCount As Long 
    Dim lOldUbound As Long 

    If Me.ChildCount = 0 Then 
     lRowCount = 1 
    Else 
     lRowCount = Me.ChildCount 
    End If 

    ReDim vaReturn(1 To lRowCount, 1 To 1) 

    For i = 1 To lRowCount 
     vaReturn(i, 1) = Me.Data 
    Next i 

    For i = 1 To gclsData.Count 
     If gclsData.Data(i).ParentID = Me.ID Then 
      lChildCount = lChildCount + 1 
      vaChild = gclsData.Data(i).Tree 
      lOldUbound = UBound(vaReturn, 2) 
      ReDim Preserve vaReturn(1 To lRowCount, 1 To UBound(vaReturn, 2) + UBound(vaChild, 2)) 
      For j = 1 To UBound(vaChild, 2) 
       vaReturn(lChildCount, j + 1) = vaChild(1, j) 
      Next j 
     End If 
    Next i 

    Tree = vaReturn 

End Property 

Suivant faire un module de classe et nommez-CData et de mettre ce code dans ce

Option Explicit 

Private mcolCDatas As Collection 

Private Sub Class_Initialize() 

    Set mcolCDatas = New Collection 

End Sub 

Private Sub Class_Terminate() 

    Set mcolCDatas = Nothing 

End Sub 

Public Sub Add(clsDatum As CDatum) 

    mcolCDatas.Add clsDatum, clsDatum.ID 

End Sub 

Public Property Get Count() As Long 

    Count = mcolCDatas.Count 

End Property 

Public Property Get Data(vItem As Variant) As CDatum 

    Set Data = mcolCDatas.Item(vItem) 

End Property 

Public Property Get FilterByTopLevel() As CData 

    Dim clsReturn As CData 
    Dim i As Long 
    Dim clsDatum As CDatum 

    Set clsReturn = New CData 

    For i = 1 To Me.Count 
     Set clsDatum = Me.Data(i) 
     If clsDatum.ParentID = 0 Then 
      clsReturn.Add clsDatum 
     End If 
    Next i 

    Set FilterByTopLevel = clsReturn 

End Property 

Suivant insérer un module standard et de mettre ce code dans ce

Option Explicit 

Public gclsData As CData 

Sub FillClass() 

    Dim clsDatum As CDatum 
    Dim rCell As Range 

    Set gclsData = New CData 

    For Each rCell In Sheet1.Range("A2:A7").Cells 
     Set clsDatum = New CDatum 
     clsDatum.ID = rCell.Value 
     clsDatum.Data = rCell.Offset(0, 2).Value 
     clsDatum.ParentID = rCell.Offset(0, 1).Value 
     gclsData.Add clsDatum 
    Next rCell 

End Sub 

Sub PrintTree() 

    Dim clsDatum As CDatum 
    Dim clsTopLevel As CData 
    Dim i As Long 
    Dim ws As Worksheet 
    Dim vaData As Variant 
    Dim lRowCount As Long 

    FillClass 

    Set clsTopLevel = gclsData.FilterByTopLevel 
    Set ws = ThisWorkbook.Worksheets.Add 

    lRowCount = 1 

    For i = 1 To clsTopLevel.Count 
     Set clsDatum = clsTopLevel.Data(i) 
     vaData = clsDatum.Tree 
     ws.Cells(lRowCount, 1).Resize(UBound(vaData, 1), UBound(vaData, 2)).Value = vaData 
     lRowCount = lRowCount + UBound(vaData, 1) 
    Next i 

End Sub 

Ensuite, exécutez la PrintTree sub. Ou vous pouvez télécharger le classeur que j'ai utilisé pour le tester et le suivre.

http://www.dailydoseofexcel.com/excel/TestDataClass.zip

+1

Merci Dick pour votre temps, votre réponse est impressionnante. – Alqin

+0

Il faut un peu de temps pour analyser – Alqin

+0

Oh, je parie que c'est le cas. Il parcourt chaque instance plusieurs fois pour construire l'arbre. Si vous pouvez le faire avec SQL ou un tableau croisé dynamique, ce serait certainement plus rapide. Je ne pouvais pas le faire avec l'un ou l'autre. Par curiosité, combien de lignes, quel est l'arbre le plus profond, et combien de temps cela prend-il pour courir? –