home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1999 January / pcwk_01_1999.iso / Wtestowe / Vistdstd / Install / Data.Z / Orgchart.BAS < prev    next >
BASIC Source File  |  1996-09-05  |  34KB  |  842 lines

  1. Attribute VB_Name = "ORGCHART1"
  2. '------------------------------------------------------------------------------
  3. '------------------------------------------------------------------------------
  4. '--
  5. '--                       Visio Organization Chart AddOn
  6. '--                       (C)1993 Shapeware Corporation
  7. '--
  8. '--   File Name : OrgChart.bas
  9. '--
  10. '-- Description : Main module for the OrgChart AddOn
  11. '--
  12. '-- Audit Trail:
  13. '--
  14. '-- 09/**/93 - v2.001 - aw -    The procedures that have comments in them are modified,
  15. '--                             all totally changed. Code has been deleted, and bugs that
  16. '--                             had to do with reading orgchart from Visio is corrected.
  17. '--                             CreateOrgChart now colors the 2D shapes again.
  18. '--                             ReadOrgChart can read the orgchart both when user uses
  19. '--                             a combination of 1D and 2D shapes, or 2D shapes and control
  20. '--                             points. In the case of 2D/1D, the y-value of the 2D shape's
  21. '--                             connection point (where the 1D shape is connected )decides
  22. '--                             which 2D shape is partent of another 2D shape.
  23. '-- 07/**/93 - v2.000 - bl -    Added code for read orgchart in menu chart.
  24. '-- **/**/** - v1.001 - rf -    Updated code.
  25. '-- **/**/** - v1.000 - ** -    Created.(PM or TB)
  26. '--
  27. '------------------------------------------------------------------------------
  28. '------------------------------------------------------------------------------
  29. Option Explicit
  30. 'Option Base 1
  31.  
  32. 'Maximum number of objects for arrays used when create orgchart
  33. Global Const cMax% = 60
  34.  
  35. '-- Constants used to identify the items in the chart menu
  36. Global Const ShowItems% = 0
  37. Global Const CreateChart% = 1
  38. Global Const ReadChart% = 2
  39.  
  40. '-- Constants used to identify the items in the command menu
  41. Global Const Promote% = 0
  42. Global Const Demote% = 1
  43. Global Const Delet% = 2
  44. Global Const DeleteBranch% = 3
  45.  
  46. '-- Used when ask user to clear the orgchart scetched in the outline control
  47. Global Const MB_YESNO = 4
  48. Global Const IDNO = 7
  49.  
  50. '-- Key Codes
  51. Global Const KEY_BACK = &H8
  52. Global Const KEY_TAB = &H9
  53. Global Const KEY_SHIFT = &H10
  54. Global Const KEY_RETURN = &HD
  55. Global Const KEY_LEFT = &H25
  56. Global Const KEY_UP = &H26
  57. Global Const KEY_RIGHT = &H27
  58. Global Const KEY_DOWN = &H28
  59.  
  60. Global Const SHIFT_MASK = 1
  61. Global Const CTRL_MASK = 2
  62. Global Const ALT_MASK = 4
  63.  
  64. Global Const CURSOR_HOURGLASS = 11
  65. Global Const CURSOR_NORMAL = 1
  66.  
  67. Function BuildOneD(cShapesCount As Integer, objDocument As Visio.Document) As String
  68. '------------------------------------------------------------------------------------------------
  69. '------------------------------------------------------------------------------------------------
  70. '-- Calling function:   ReadOrgChart()
  71. '-- Functions called:
  72. '-- This function has an effect only when the user has connected the 2D
  73. '-- BuildOneD loops through all the shapes, if it's a one dimensional shape, it checks it's
  74. '-- connections, and saves what is connected to what. This function uses heuristics, it assumes
  75. '-- that if a 1D shape is glued to the bottom most connection point of the 2D shape, (connection
  76. '-- no 4), this 2D shape is the parent of the shape in the other end of the 1D which will be
  77. '-- connections no 2. Format of the string will be: {003 001}{002 001}.... if 003 and 002
  78. '-- are children of 001
  79. '--
  80.  
  81.     Dim i As Integer
  82.     Dim strS As String
  83.     Dim objShapes As Visio.Shapes, objConnections As Visio.Connects
  84.     Dim TB As String
  85.  
  86.     TB = Chr$(9)
  87.  
  88.     Set objShapes = objDocument.Pages(1).Shapes
  89.     For i = 1 To cShapesCount
  90.         If objShapes(i).OneD Then
  91.             Set objConnections = objShapes(i).Connects
  92.             If (objConnections.Count = 2) Then
  93.                 'Connections(1) has highest y-value (highest y-value = from shape)
  94.                 If objConnections(1).ToPart = (visConnectionPoint + visRowFirst + 1) Then
  95.                     strS = strS & "{" & Format$(objConnections(1).ToSheet.Index, "000") & TB & Format$(objConnections(2).ToSheet.Index, "000") & "}"
  96.                 Else    'Connections(2) has highest y-value
  97.                     strS = strS & "{" & Format$(objConnections(2).ToSheet.Index, "000") & TB & Format$(objConnections(1).ToSheet.Index, "000") & "}"
  98.                 End If
  99.             End If
  100.         End If
  101.     Next i
  102.     BuildOneD = strS
  103. End Function
  104.  
  105. Function BuildTwoD(cShapesCount As Integer, objDocument As Visio.Document) As String
  106. '------------------------------------------------------------------------------------------------
  107. '------------------------------------------------------------------------------------------------
  108. '-- Calling function:   ReadOrgChart()
  109. '-- Functions called:
  110. '-- BuildTwoD loops through all the shapes, and if it's a two dimensional shape it checks it's
  111. '-- connections, and saves what is connected to what. Format of the string will be..
  112. '-- 001PeterCR
  113. '-- 002TroyCR
  114. '-- 003AirenCR.....
  115. '--
  116.     
  117.     Dim i As Integer
  118.     Dim strS As String
  119.     Dim objShapes As Visio.Shapes, objConnections As Visio.Connects
  120.     Dim CR As String, TB As String
  121.  
  122.     CR = Chr$(13): TB = Chr$(9)
  123.  
  124.     Set objShapes = objDocument.Pages(1).Shapes
  125.     For i = 1 To cShapesCount
  126.         If Not objShapes(i).OneD Then
  127.             strS = strS & Format$(Str$(i), "000") & objShapes(i).Text '& CR
  128.             Set objConnections = objShapes(i).Connects
  129.             '-- This is only the case if the user choses to use the 2D shape's control point to
  130.             '-- to connect to another shape instead of 1D connectors.
  131.             If objConnections.Count > 0 Then
  132.                 strS = strS & TB & Format$(objConnections(1).ToSheet.Index, "000")
  133.             End If
  134.             strS = strS & CR
  135.         End If
  136.     Next i
  137.     BuildTwoD = strS
  138. End Function
  139.  
  140. Sub ConvertStr(strTwoD As String, cShapesCount As Integer)
  141. '------------------------------------------------------------------------------------------------
  142. '------------------------------------------------------------------------------------------------
  143. '-- Calling function:   ReadOrgChart()
  144. '-- Functions called:
  145. '-- ConvertStr loops through all the shapes in strTwoD and changes the format from being a list
  146. '-- of shapes, each followed by their parent, to a list of shapes, each followed by their
  147. '-- children.
  148. '--
  149.  
  150.     Dim i As Integer, iTab As Integer, iPos As Integer, iCr As Integer
  151.     Dim strParent As String, strShape As String, strRside As String
  152.     Dim CR As String, TB As String
  153.  
  154.     CR = Chr$(13): TB = Chr$(9)
  155.     
  156.     For i = 1 To cShapesCount
  157.         iPos = InStr(strTwoD, Format$(i, "000"))
  158.          If iPos <> 0 Then
  159.             strShape = Mid$(strTwoD, iPos, 3)
  160.             iCr = InStr(iPos, strTwoD, CR)
  161.             iTab = InStr(iPos, strTwoD, TB)
  162.             '-- Take the parent and find the line it's on, and add the current shape
  163.             '-- to it's list of children.
  164.             If iTab <> 0 And iTab < iCr Then
  165.                 strParent = Mid$(strTwoD, iTab + 1, 3)
  166.                 iPos = InStr(strTwoD, CR & strParent)
  167.                 iPos = iPos + 1                 '-- Get pass the CR character
  168.                 iCr = InStr(iPos, strTwoD, CR)
  169.                 strRside = Right$(strTwoD, Len(strTwoD) - (iCr - 1))
  170.                 strTwoD = Left$(strTwoD, iCr - 1) & "#" & strShape & strRside
  171.                 '-- Go back to the current shape again, and remove the parent in the list.
  172.                 iPos = InStr(strTwoD, Format$(i, "000"))
  173.                 iPos = InStr(iPos, strTwoD, TB & strParent)
  174.                 strRside = Right$(strTwoD, Len(strTwoD) - (iPos + 3))
  175.                 strTwoD = Left$(strTwoD, iPos - 1) & strRside
  176.             End If
  177.         End If
  178.     Next i
  179. End Sub
  180.  
  181. Sub CreateOrgChart()
  182. '------------------------------------------------------------------------------------------------
  183. '------------------------------------------------------------------------------------------------
  184. '-- Calling function:   frmOrgChart.mnuChartItem_Click()
  185. '-- Functions called:   DrawOrgChart()
  186. '-- CreateOrgChart loops through the items in the form's outline control and finds the max level,
  187. '-- numbers of leaves, and parent chain. It calls DrawOrgChart which draws the organizational
  188. '-- chart in Visio.
  189. '--
  190.     ReDim rgParent(cMax) As Integer, rgLeft(cMax) As Integer, rgRight(cMax) As Integer
  191.     Dim cLevels As Integer, cLeaves As Integer, fIsLeaf As Integer
  192.     Dim iIndex  As Integer, iIndent As Integer
  193.     
  194.     cLevels = 0
  195.     cLeaves = 0
  196.  
  197.     For iIndex = 0 To frmOrgChart.Outline1.ListCount - 1
  198.  
  199.         If frmOrgChart.Outline1.Indent(iIndex) < 1 Then
  200.             rgParent(iIndex) = -1           'the root, has no parent
  201.         ElseIf frmOrgChart.Outline1.Indent(iIndex) > frmOrgChart.Outline1.Indent(iIndex - 1) Then
  202.             rgParent(iIndex) = iIndex - 1
  203.         Else
  204.             iIndent = iIndex - 1
  205.             While frmOrgChart.Outline1.Indent(iIndex) <> frmOrgChart.Outline1.Indent(iIndent)
  206.                 iIndent = rgParent(iIndent)
  207.             Wend
  208.             rgParent(iIndex) = rgParent(iIndent)
  209.         End If
  210.   
  211.         '-- The item is a leaf if it doesn't have any children
  212.         fIsLeaf = Not (frmOrgChart.Outline1.HasSubItems(iIndex))
  213.  
  214.         '-- If it's a leaf, then set it's left- and right "pointer" to NULL
  215.         If Not fIsLeaf Then
  216.             rgLeft(iIndex) = -1
  217.             rgRight(iIndex) = -1
  218.         Else
  219.             rgLeft(iIndex) = cLeaves
  220.             rgRight(iIndex) = cLeaves
  221.             iIndent = rgParent(iIndex)
  222.             While iIndent <> -1
  223.                 If rgLeft(iIndent) = -1 Then rgLeft(iIndent) = cLeaves
  224.                 rgRight(iIndent) = cLeaves
  225.                 iIndent = rgParent(iIndent)
  226.             Wend
  227.         End If
  228.   
  229.         If frmOrgChart.Outline1.Indent(iIndex) > cLevels Then
  230.             cLevels = frmOrgChart.Outline1.Indent(iIndex)
  231.         End If
  232.         
  233.         If fIsLeaf Then cLeaves = cLeaves + 1
  234.     Next iIndex
  235.  
  236.     DrawOrgChart rgParent(), rgLeft(), rgRight(), cLeaves, cLevels
  237.     Exit Sub
  238. End Sub
  239.  
  240. Sub DeleteItem()
  241. '------------------------------------------------------------------------------------------------
  242. '------------------------------------------------------------------------------------------------
  243. '-- Calling function:   frmOrgChart.mnuCommandItem()
  244. '-- Functions called:   SuperExpand(), PromoteChild(), TopExpand(), UpdateFields()
  245. '-- DeleteItem has to update the indentation level for all of the children of the item to be
  246. '-- deleted before the item is removed since otherwise the children will be deleted as well.
  247. '--
  248.     Dim ctl As Control
  249.     
  250.     'Short form...
  251.     Set ctl = frmOrgChart.Outline1
  252.  
  253.     'SuperExpand (ctl.ListIndex)
  254.     Select Case ctl.ListIndex
  255.         Case -1:
  256.             Beep       '-- Nothing in the outline control
  257.         Case 0:        '-- Try to delete the root
  258.             If ctl.HasSubItems(ctl.ListIndex) Then
  259.                 Beep
  260.                 'If one child - ok
  261.                 'If more than one child then tell user it cannot be done
  262.             Else
  263.                 ctl.RemoveItem ctl.ListIndex
  264.             End If
  265.         Case Else:
  266.             '-- Delete the item after all of it's children's indent have been updated.
  267.             PromoteChild ctl.ListIndex + 1, (ctl.Indent(ctl.ListIndex))
  268.             ctl.RemoveItem ctl.ListIndex
  269.     End Select
  270.     UpdateFields
  271. End Sub
  272.  
  273. Sub DeleteItemBranch()
  274. '------------------------------------------------------------------------------------------------
  275. '------------------------------------------------------------------------------------------------
  276. '-- Calling function:   frmOrgChart.mnuCommandItem()
  277. '-- Functions called:
  278. '-- DeleteItemBranch deletes the item identified by ListIndex, and all of it's children.
  279. '-- (RemoveItem method removes the item and all of it's subordinate items for an outline
  280. '-- control).
  281. '--
  282.     Dim ctl As Control
  283.  
  284.     'Short form...
  285.     Set ctl = frmOrgChart.Outline1
  286.     
  287.     If ctl.ListIndex <> -1 Then
  288.         ctl.RemoveItem (ctl.ListIndex)
  289.         frmOrgChart.Outline1.AddItem ""
  290.         ctl.ListIndex = 0
  291.         ctl.Indent(ctl.ListIndex) = 0
  292.         UpdateFields
  293.     Else
  294.         Beep
  295.     End If
  296. End Sub
  297.  
  298. Sub DemoteChild(iIndex As Integer, iIndent As Integer)
  299. '------------------------------------------------------------------------------------------------
  300. '------------------------------------------------------------------------------------------------
  301. '-- Calling function:   DeleteItem()
  302. '-- Functions called:   DemoteChild() - recursive
  303. '-- DemoteChild loops through the children of the item (items in the list can be children if
  304. '-- their index follow in sequence after the index of The item, and they have an indentation
  305. '-- larger than the indentation for The item.)
  306. '--
  307.  
  308.     Dim ctl As Control
  309.  
  310.     '-- Short form...
  311.     Set ctl = frmOrgChart.Outline1
  312.  
  313.     '-- Stop recursion at this point..
  314.     If iIndex = ctl.ListCount Then
  315.         Exit Sub
  316.     ElseIf Not ctl.Indent(iIndex) > iIndent Then
  317.         Exit Sub
  318.     End If
  319.     
  320.     '-- Adjust indentation..
  321.     ctl.Indent(iIndex) = ctl.Indent(iIndex) + 1
  322.     SuperExpand iIndex
  323.     '-- Call recursively..
  324.     DemoteChild iIndex + 1, iIndent
  325. End Sub
  326.  
  327. Sub DemoteItem()
  328. '------------------------------------------------------------------------------------------------
  329. '------------------------------------------------------------------------------------------------
  330. '-- Calling function:   mnuCommandItem()
  331. '-- Functions called:   DemoteChild()
  332. '-- DemoteItem adjust the indentation for the item itself, and then adjust the indentation
  333. '-- for the item's child. However, if the outline control is empty or the item is the root,
  334. '-- or the item doesn't have a preceding item with indent level equal or greater to it's own,
  335. '-- it'll just beep.
  336. '--
  337.  
  338.     Dim ctl As Control
  339.     Dim iIndent As Integer
  340.  
  341.     'Short form...
  342.     Set ctl = frmOrgChart.Outline1
  343.     
  344.     If ctl.ListIndex <> -1 Then
  345.         '-- Cannot demote the item if it's a root, or if there's no item preceding it with
  346.         '-- indent level equal or larger to it's own indent level.
  347.         If ctl.Indent(ctl.ListIndex) > 0 Then
  348.             If Not ctl.Indent(ctl.ListIndex - 1) < ctl.Indent(ctl.ListIndex) Then
  349.                 iIndent = ctl.Indent(ctl.ListIndex)
  350.                 ctl.Indent(ctl.ListIndex) = ctl.Indent(ctl.ListIndex) + 1
  351.                 '-- It still eludes me why they disappear, but for now solve
  352.                 '-- the problem by expanding..
  353.                 SuperExpand (ctl.ListIndex)
  354.                 DemoteChild ctl.ListIndex + 1, iIndent
  355.             Else
  356.                 Beep
  357.             End If
  358.         Else
  359.             Beep
  360.         End If
  361.     Else
  362.         Beep
  363.     End If
  364. End Sub
  365.  
  366. Private Sub DrawOrgChart(rgParent() As Integer, rgLeft() As Integer, rgRight() As Integer, cLeaves As Integer, cLevels As Integer)
  367. '------------------------------------------------------------------------------------------------
  368. '------------------------------------------------------------------------------------------------
  369. '-- Calling function:   CreateOrgChart()
  370. '-- Functions called:   GlueMe(), PosX(), PosY()
  371. '-- DrawOrgChart sets up the environment in Visio (exits if it cannot create or get the
  372. '-- existing Visio) and then drops instances of the master "Position" onto the page according
  373. '-- to the number of items in the form's outline control. It assigns text to the instances, sets
  374. '-- their fill color, and calls GlueMe in order to connect the different instances of "Position".
  375. '--
  376.     
  377.     ReDim objArray(cMax) As Object
  378.     Dim objPage As Visio.Page, objStencil As Visio.Document, objMasters As Visio.Masters
  379.     Dim objMaster As Visio.Master, objParent As Object, objShapes As Visio.Shapes
  380.     Dim iIndex As Integer, iIndent As Integer
  381.     Dim X As Double, Y As Double
  382.  
  383.     'Get the active instance of Visio, or run one
  384.     If vaoGetObject() <> visOK Then
  385.         MsgBox "Cannot get an instance of Visio."
  386.         End
  387.     End If
  388.  
  389.     'Create a new document based on sample.vst
  390.     'and get the stencil, master, and page objects
  391.     g_appVisio.Documents.Add ("VB Solutions.vst")
  392.     Set objStencil = g_appVisio.Documents.Item("VB Solutions.vss")
  393.     Set objMasters = objStencil.Masters
  394.     Set objMaster = objMasters.Item("Position")
  395.     Set objPage = g_appVisio.ActivePage
  396.     
  397.     'Calculat the pin of each Position shape based on cLeaves and cLevels.
  398.     For iIndex = 0 To frmOrgChart.Outline1.ListCount - 1
  399.         X = PosX(cLeaves, rgRight(iIndex), rgLeft(iIndex))
  400.         Y = PosY(cLevels, iIndex)
  401.         Set objArray(iIndex) = objPage.Drop(objMaster, X, Y)
  402.         objArray(iIndex).Text = (frmOrgChart.Outline1.List(iIndex))
  403.         Set objShapes = objArray(iIndex).Shapes
  404.     Next iIndex
  405.  
  406.     'Glue each child to its parent
  407.     For iIndex = 0 To frmOrgChart.Outline1.ListCount - 1
  408.         iIndent = rgParent(iIndex)
  409.         If iIndent <> -1 Then
  410.             objArray(iIndex).Cells("Controls.X1").GlueTo objArray(rgParent(iIndex)).Cells("Connections.X4")
  411.         End If
  412.     Next iIndex
  413. End Sub
  414.  
  415. Function FindRoot(strTwoD As String) As String
  416. '------------------------------------------------------------------------------------------------
  417. '------------------------------------------------------------------------------------------------
  418. '-- Calling function:   ReadOrgChart()
  419. '-- Functions called:
  420. '-- FindRoot loops through all the shapes and decides which shape is the root in the
  421. '-- organizational tree.
  422. '--
  423.  
  424.     Dim iTab As Integer, iCr As Integer, iPos As Integer, iStart As Integer
  425.     Dim CR As String, TB As String, strRoot As String
  426.  
  427.     CR = Chr$(13): TB = Chr$(9)
  428.     iStart = 1
  429.  
  430.     strRoot = Mid$(strTwoD, iStart, 3)
  431.     iTab = InStr(iStart, strTwoD, TB)
  432.     iCr = InStr(iStart, strTwoD, CR)
  433.  
  434.     Do While (iTab < iCr)
  435.         iStart = iCr + 1
  436.         strRoot = Mid$(strTwoD, iStart, 3)
  437.         iTab = InStr(iStart, strTwoD, TB)
  438.         iCr = InStr(iStart, strTwoD, CR)
  439.     Loop
  440.     FindRoot = strRoot
  441. End Function
  442.  
  443. Sub ImportStr(strTwoD As String, ByVal strTop As String, Indent As Integer)
  444. '------------------------------------------------------------------------------------------------
  445. '------------------------------------------------------------------------------------------------
  446. '-- Calling function:   ReadOrgChart()
  447. '-- Functions called:   ImportStr() - recursive
  448. '-- ImportStr loops through all the shapes in strTwoD and sketches the outline of the
  449. '-- organizational chart in the form's outline control.
  450. '--
  451.  
  452.     Dim i As Integer, iPos As Integer, iNo As Integer, iCr As Integer
  453.     Dim strNewTop As String, temp As String
  454.     Dim CR As String, TB As String
  455.  
  456.     CR = Chr$(13): TB = Chr$(9)
  457.     strNewTop = strTop
  458.     iPos = InStr(1, strTwoD, strNewTop)
  459.     
  460.     If iPos <> 1 Then
  461.         While Mid$(strTwoD, iPos - 1, 1) = "#"
  462.             iPos = InStr(iPos + 1, strTwoD, strNewTop)
  463.         Wend
  464.     End If
  465.  
  466.     iPos = iPos + 3
  467.     iCr = InStr(iPos, strTwoD, CR)
  468.     iNo = InStr(iPos, strTwoD, "#")
  469.  
  470.     If iNo <> 0 And iNo < iCr Then
  471.         temp = Mid$(strTwoD, iPos, iNo - iPos)
  472.     Else
  473.         temp = Mid$(strTwoD, iPos, iCr - iPos)
  474.     End If
  475.  
  476.     frmOrgChart.Outline1.AddItem temp
  477.     frmOrgChart.Outline1.Indent(frmOrgChart.Outline1.ListCount - 1) = Indent
  478.  
  479.     Do While iNo <> 0 And iNo < iCr
  480.         temp = Mid$(strTwoD, iNo + 1, 3)
  481.         ImportStr strTwoD, temp, Indent + 1
  482.         iNo = InStr(iNo + 1, strTwoD, "#")
  483.     Loop
  484. End Sub
  485.  
  486. Sub MergeStr(strOneDShapes As String, strTwoDShapes As String)
  487. '------------------------------------------------------------------------------------------------
  488. '------------------------------------------------------------------------------------------------
  489. '-- Calling function:   ReadOrgChart()
  490. '-- Functions called:
  491. '-- MergeStr merges the two strings, strOneD and strTwoD, and leave the result in strTwoD.
  492. '-- (If the user has used the 2D shape's control point to connect to the other shape,
  493. '-- no merging is needed.)
  494. '--
  495.     Dim iConnections As Integer, i As Integer, iCr As Integer, iPos As Integer
  496.     Dim iStart1 As Integer, iStart2 As Integer
  497.     Dim strFrom As String, strTo As String
  498.     Dim CR As String, TB As String
  499.  
  500.     CR = Chr$(13): TB = Chr$(9)
  501.     iStart1 = 2: iStart2 = 1
  502.     iConnections = Len(strOneDShapes) / 9
  503.  
  504.     For i = 1 To iConnections                   'Parent/Child connections
  505.         '-- String of OneD shapes...
  506.         strFrom = Mid$(strOneDShapes, iStart1, 3)
  507.         iStart1 = iStart1 + 4
  508.         strTo = Mid$(strOneDShapes, iStart1, 3)
  509.         '-- String of TwoD shapes...
  510.         iPos = InStr(1, strTwoDShapes, strFrom)
  511.         iStart2 = iPos
  512.         iCr = InStr(iStart2, strTwoDShapes, CR)
  513.         'If we're at the end of the string, prepare for appending....
  514.         If iCr = 0 Then
  515.             iCr = Len(strTwoDShapes) + 1
  516.         End If
  517.         strFrom = Right$(strTwoDShapes, Len(strTwoDShapes) - (iCr - 1))
  518.         strTwoDShapes = Left$(strTwoDShapes, iCr - 1) & TB & strTo & strFrom
  519.         iStart1 = iStart1 + 5
  520.     Next i
  521. End Sub
  522.  
  523. Sub movedown()
  524. '/************* Needs to be worked on *********/
  525. Dim dumnum As Variant
  526. Dim intnum As Integer
  527. Dim intabv As Integer
  528. Dim intblw As Integer
  529. Dim strT As String
  530. Dim ctl As Control
  531.  
  532.     '-- short form...
  533.     Set ctl = frmOrgChart.Outline1
  534.  
  535.     ctl.Refresh
  536.     If ctl.ListIndex = 0 Then
  537.         Beep
  538.         Exit Sub
  539.     End If
  540.     intnum = ctl.ListIndex + 1
  541.     If ctl.ListCount - intnum > 0 Then
  542.         dumnum = Abs(ctl.Indent(intnum) - ctl.Indent(ctl.ListIndex))
  543.         If dumnum > 1 Then
  544.             Beep
  545.             Exit Sub
  546.         Else
  547.             intblw = ctl.Indent(intnum)
  548.         End If
  549.     Else
  550.         Beep
  551.         Exit Sub
  552.     End If
  553.     intnum = intnum - 2
  554.     If intnum > -1 Then
  555.         intabv = ctl.Indent(intnum)
  556.     Else
  557.         intabv = intblw
  558.     End If
  559.     If (ctl.ListIndex + 2) < ctl.ListCount Then
  560.         intnum = Abs(ctl.Indent(ctl.ListIndex) - ctl.Indent(ctl.ListIndex + 2))
  561.     Else
  562.         intnum = 1
  563.     End If
  564.     dumnum = Abs(intabv - intblw)
  565.     If dumnum < 2 And intnum < 2 Then
  566.         strT = ctl.List(ctl.ListIndex)
  567.         ctl.List(ctl.ListIndex) = ctl.List(ctl.ListIndex + 1)
  568.         ctl.List(ctl.ListIndex + 1) = strT
  569.         ctl.Indent(ctl.ListIndex + 1) = ctl.Indent(ctl.ListIndex)
  570.         ctl.Indent(ctl.ListIndex) = intblw
  571.         ctl.ListIndex = ctl.ListIndex + 1
  572.         SuperExpand (ctl.ListIndex)
  573.         TopExpand (ctl.ListIndex)
  574.     Else
  575.         Beep
  576.     End If
  577. End Sub
  578.  
  579. Sub moveup()
  580. '/******** Needs to be worked on ********/
  581.     Dim Thing As String
  582.     Dim ctl As Control
  583.  
  584.     '-- Short form...
  585.     Set ctl = frmOrgChart.Outline1
  586.  
  587.     Thing = ctl.List(ctl.ListIndex)
  588.     If ctl.ListIndex - 1 >= 0 Then
  589.         ctl.ListIndex = ctl.ListIndex - 1
  590.         movedown
  591.         If ctl.ListIndex + 1 >= ctl.ListCount Then
  592.             ctl.ListIndex = ctl.ListIndex - 1
  593.             Exit Sub
  594.         End If
  595.         If ctl.List(ctl.ListIndex + 1) <> Thing Then
  596.             ctl.ListIndex = ctl.ListIndex - 1
  597.         Else
  598.             ctl.ListIndex = ctl.ListIndex + 1
  599.         End If
  600.     Else
  601.         Beep
  602.     End If
  603. End Sub
  604.  
  605. Private Function PosX(cLeaves As Integer, aright As Integer, aleft As Integer) As Double
  606. '------------------------------------------------------------------------------------------------
  607. '------------------------------------------------------------------------------------------------
  608. '-- Calling funcions:    DrawOrgChart()
  609. '-- Functions called:
  610. '-- PosX calculates the x position for where to drop the instance of the master based on how
  611. '-- many children the object has.
  612. '--
  613.     Dim MulX As Double, OffX As Double
  614.     
  615.     MulX = 1.25
  616.     OffX = 5# - (1# * cLeaves) / 2
  617.     PosX = OffX + MulX * (aright + aleft) / 2#
  618. End Function
  619.  
  620. Private Function PosY(cLevels As Integer, Index As Integer) As Double
  621. '------------------------------------------------------------------------------------------------
  622. '------------------------------------------------------------------------------------------------
  623. '-- Calling funcions:    DrawOrgChart()
  624. '-- Functions called:
  625. '-- PosY calculates the y position for where to drop the instance of the master based on how
  626. '-- many levels the tree has.
  627. '--
  628.  
  629.     Dim OffY As Double
  630.     Dim separation As Double
  631.  
  632.     separation = 1
  633.     OffY = 4.5 + (cLevels * separation) / 2
  634.     PosY = OffY - (frmOrgChart.Outline1.Indent(Index)) * separation
  635. End Function
  636.  
  637. Sub PromoteChild(iIndex As Integer, iIndent As Integer)
  638. '------------------------------------------------------------------------------------------------
  639. '------------------------------------------------------------------------------------------------
  640. '-- Calling function:   DeleteItem()
  641. '-- Functions called:   PromoteChild() - recursive
  642. '-- PromoteChild loops through the children of The item (items in the list can be children if
  643. '-- their index follow in sequence after the index of The item, and they have an indentation
  644. '-- larger than the indentation for The item.)
  645. '--
  646.  
  647.     Dim ctl As Control
  648.  
  649.     '-- Short form...
  650.     Set ctl = frmOrgChart.Outline1
  651.  
  652.     '-- Stop recursion at this point..
  653.     '-- Looks pretty stupid to use an if/end for this, but basic's OR checks doesn't skip
  654.     '-- the second case if the first evaluated to true, which in our case would result in
  655.     '-- a control error message.
  656.     If iIndex = ctl.ListCount Then
  657.         Exit Sub
  658.     ElseIf Not ctl.Indent(iIndex) > iIndent Then
  659.         Exit Sub
  660.     End If
  661.     
  662.     PromoteChild iIndex + 1, iIndent
  663.     '-- Adjust indentation..
  664.     ctl.Indent(iIndex) = ctl.Indent(iIndex) - 1
  665. End Sub
  666.  
  667. Sub PromoteItem()
  668. '------------------------------------------------------------------------------------------------
  669. '------------------------------------------------------------------------------------------------
  670. '-- Calling function :  frmOrgChart.mnuCommandItem()
  671. '-- Functions called :  PromoteChild()
  672. '-- PromoteItem adjust the indentation of the item's child, and then adjust the indentation
  673. '-- for the item itself. However, if the outline control is empty or the item's indentation
  674. '-- level is smaller than 2, it'll just beep.
  675. '--
  676.  
  677.     Dim ctl As Control
  678.  
  679.     '-- Short form...
  680.     Set ctl = frmOrgChart.Outline1
  681.  
  682.     If ctl.ListIndex <> -1 Then
  683.         '-- Cannot promote an item with indent 0 or 1 since we want one root only..
  684.         If ctl.Indent(ctl.ListIndex) > 1 Then
  685.             PromoteChild ctl.ListIndex + 1, (ctl.Indent(ctl.ListIndex))
  686.             ctl.Indent(ctl.ListIndex) = ctl.Indent(ctl.ListIndex) - 1
  687.             UpdateFields
  688.         Else
  689.             Beep
  690.         End If
  691.     Else
  692.         Beep
  693.     End If
  694. End Sub
  695.  
  696. Sub ReadOrgChart()
  697. '------------------------------------------------------------------------------------------------
  698. '------------------------------------------------------------------------------------------------
  699. '-- Calling function:   frmOrgChart.mnuChartItem_Click()
  700. '-- Functions called:   BuildOneD(), BuildTwoD(), MergeStr(), ConvertStr(), ImportStr(),
  701. '--                     FindRoot()
  702. '-- ReadOrgChart creates or get the excisting Visio, reads the number of shapes that are on the
  703. '-- active document's page, seperates these shapes into one dimensional and two dimensional,
  704. '-- merge the two sets in order to build the tree in the frmOrgChart's outline control
  705. '--
  706.     Dim objDocument As Visio.Document
  707.     Dim cShapesCount As Integer, i As Integer
  708.     Dim strOneD As String, strTwoD As String, strRoot As String
  709.  
  710.     On Error GoTo LBLReadOrgChartError
  711.     
  712.     If vaoGetObject() <> visOK Then
  713.         MsgBox "Cannot achieve an instance of Visio!"
  714.         End
  715.     End If
  716.  
  717.     '-- Make sure that the drawing window is the active window because if we delete
  718.     '-- a drawing window, the stencil window becomes active
  719.     For i = 1 To g_appVisio.Windows.Count
  720.         If g_appVisio.Windows(i).Type = visDrawing Then
  721.             g_appVisio.Windows(i).Activate
  722.         End If
  723.     Next i
  724.  
  725.     Screen.MousePointer = CURSOR_HOURGLASS
  726.     Set objDocument = g_appVisio.ActiveDocument
  727.     cShapesCount = objDocument.Pages(1).Shapes.Count
  728.     strOneD = BuildOneD(cShapesCount, objDocument)
  729.     strTwoD = BuildTwoD(cShapesCount, objDocument)
  730.     If strOneD <> "" Then
  731.         MergeStr strOneD, strTwoD
  732.     End If
  733.     strRoot = FindRoot(strTwoD)
  734.     ConvertStr strTwoD, cShapesCount
  735.     
  736.     frmOrgChart.Text1.Text = " "
  737.     frmOrgChart.Outline1.Clear
  738.  
  739.     '-- Build the org chart tree in the outline control
  740.     ImportStr strTwoD, strRoot, 0
  741.     '-- Expand the tree
  742.     If frmOrgChart.mnuChartItem(ShowItems).Checked = True Then
  743.         For i = 1 To frmOrgChart.Outline1.ListCount - 1
  744.             TopExpand (i)
  745.         Next
  746.     End If
  747.     frmOrgChart.Outline1.ListIndex = frmOrgChart.Outline1.ListCount - 1
  748.     UpdateFields
  749.     Screen.MousePointer = CURSOR_NORMAL
  750.  
  751.     Exit Sub
  752. LBLReadOrgChartError:
  753.     If objDocument Is Nothing Then
  754.         MsgBox ("There is no open document in Visio")
  755.     End If
  756.     MsgBox Error$(Err)
  757.     Exit Sub
  758. End Sub
  759.  
  760. Sub SuperExpand(Index As Integer)
  761. '------------------------------------------------------------------------------------------------
  762. '------------------------------------------------------------------------------------------------
  763. '-- Calling functions:  frmOrgChart.mnuCommandItem(), text1.keydown(), text1.keyup(),
  764. '--                     general.movedown , DemoteChilde(), PromoteAll()
  765. '-- Functions called :  SuperExpand() - recursiv
  766. '-- SuperExpand traverses the path backwards until it finds a parent which is visible, makes
  767. '-- the children for this parent visible using the expand property, and calls itself recursively
  768. '-- to see if the item (index) is now visible.
  769. '--
  770.  
  771.     Dim cCounter As Integer
  772.  
  773.     If Not (frmOrgChart.Outline1.IsItemVisible(Index)) Then
  774.         cCounter = 1
  775.         Do While Not (frmOrgChart.Outline1.IsItemVisible(Index - cCounter))
  776.             cCounter = cCounter + 1
  777.         Loop
  778.     '***********************************
  779.     '-- This line sometimes has a side effect - it adds an item to the outline orgchart tree
  780.     '-- when user hits the TAB or SHIFT/TAB. Should be corrected.
  781.          frmOrgChart.Outline1.Expand(Index - cCounter) = True
  782.         SuperExpand (Index)
  783.     End If
  784. End Sub
  785.  
  786. Function TopEngine(Index As Integer) As Integer
  787. '------------------------------------------------------------------------------------------------
  788. '------------------------------------------------------------------------------------------------
  789. '-- Calling function:   TopExpand()
  790. '-- Functions called:   TopEngine() - recursive
  791. '--
  792.  
  793.     Dim cCounter As Integer
  794.  
  795.     cCounter = 1
  796.     If frmOrgChart.Outline1.HasSubItems(Index) Then
  797.         frmOrgChart.Outline1.Expand(Index) = True
  798.             Do While (frmOrgChart.Outline1.Indent(Index + cCounter) = frmOrgChart.Outline1.Indent(Index) + 1)
  799.                 cCounter = cCounter + TopEngine(Index + cCounter)
  800.                 If Index + cCounter >= frmOrgChart.Outline1.ListCount - 1 Then Exit Do
  801.             Loop
  802.     End If
  803.     TopEngine = cCounter
  804. End Function
  805.  
  806. Sub TopExpand(Index As Integer)
  807. '------------------------------------------------------------------------------------------------
  808. '------------------------------------------------------------------------------------------------
  809. '-- Calling functions :
  810. '-- Functions called  : TopEngine()
  811. '-- TopExpands soul purpose is to call TopEngine() and to recieve whatever value it returns (a
  812. '-- value which is not needed). TopEngine needs to be a function because it calls itself, and
  813. '-- in VB you cannot ignore return values like in C. Since TopEngine needs to be called several
  814. '-- times, TopExpand functions as a filter for the useless return value and saves us variable
  815. '-- declarations everywhere else.
  816. '--
  817.     Dim iCrap As Integer
  818.     iCrap = TopEngine(Index)
  819. End Sub
  820.  
  821. Sub UpdateFields()
  822. '------------------------------------------------------------------------------------------------
  823. '------------------------------------------------------------------------------------------------
  824. '-- Calling functions:  Form_Load(), frmOrgChart.mnuCommandItem_Click(), outline1.Click(),
  825. '--                     Text1.KeyDown(), Text1.KeyUp()
  826. '-- Functions called :
  827. '-- UpdateFields checks to see if there's anything in the form's outline control, and if so,
  828. '-- updates the text control according to the outline controls text, and enables the menu item
  829. '-- "CreateOrgChart". If the outline is blank, the text box is blanked, and the menu item is
  830. '-- disabled.
  831. '--
  832.  
  833.     If Not (frmOrgChart.Outline1.ListIndex = 0 And frmOrgChart.Outline1.List(0) = "") Then
  834.         frmOrgChart.Text1.Text = frmOrgChart.Outline1.Text
  835.         frmOrgChart.mnuChartItem(CreateChart).Enabled = True
  836.     Else
  837.         frmOrgChart.Text1.Text = ""
  838.         frmOrgChart.mnuChartItem(CreateChart).Enabled = False
  839.     End If
  840. End Sub
  841.  
  842.