In a TreeView, how do I execute code only if a parent node's Image is 4 and any child's is 3?
If TreeView2.Nodes(ii).Image = 4 And TreeView2.Nodes(ii).Image = 3 Then.
For some reason this If TreeView2.Nodes(ii).Image = 4 checks the parent and child , I don't know why.
I am trying to use If TreeView2.Nodes(ii).parent.child.image=3 but it is not working right.
TreeView2.Nodes(ii).parent is always going to be Nothing. The top-level nodes in your TreeView don't have parents. When you use TreeView2.Nodes(ii).parent.child you are certain to get an error. Using parent.child would only be used to get the first child of the parent node which probably isn't what you are trying to do.
It sounds like you want to do the following:
Dim objRootNode As Node
Dim objChildNode As Node
Dim iRootCounter As Integer
Dim iChildCounter As Integer
For iRootCounter = 1 To TreeView1.Nodes.Count
Set objRootNode = TreeView1.Nodes(iRootCounter)
If objRootNode.Image = 4 Then
Set objChildNode = objRootNode.Child ' Gets first child
For iChildCounter = 1 To objRootNode.Children
If objChildNode.Image = 3 Then
' Write your code here
End If
Set objChildNode = objChildNode.Next ' Get next node
Next
End If
Next
Add your code where it says Write your code here. This is where parent has Image = 4 and child has Image = 3.
Related
We have a legacy application written in VB6 using the default Microsoft TreeView control to display hierarchical data. Since there's a lot of information in this TreeView we thought about implementing a small filter/search possibility for the users.
The first attempt was to toggle the visibility and only make nodes (and their parents) visible, that match the defined search. But that was impossible, since the default Microsoft TreeView control doesn't allow their nodes to be visible or invisible.
So the second attempt is to traverse all the nodes in the tree and ensure a node's visibility when it matches the defined search (and stop traversing). When the found node isn't the one the user is looking for he can "continue" the search and look for the next node that matches his criteria.
This works quite good so far, except for one little problem. The search doesn't work from top to bottom, since the tree is filled with data in random sort order and then sorted by setting the Sorted property of each node (legacy code). So the search is going through the randomly added nodes and the found nodes "jump" between the top level nodes (the Nodes collection of the TreeView contains all the nodes in the order they were added, not just the top level nodes and not in the order they are presented to the user).
Is there any way to get all the nodes of the tree in the order they are shown to the user? I don't like to change the legacy code that is filling the tree with data, and sorting the data before it is added to the TreeView might affect performance.
Please be aware that I'm talking about an application written in VB6, so there's no such thing as LINQ to traverse the nodes in the desired order.
Here's my searching code so far:
Private Sub cmdSearch_Click()
Dim oMatch As Node
Set oMatch = GetNextMatch
If Not (oMatch Is Nothing) Then
oMatch.EnsureVisible
oMatch.Selected = True
Me.TreeView1.SelectedItem = oMatch
Me.TreeView1.SetFocus
End If
End Sub
Private Function GetNextMatch() As Node
Dim lIndex As Long
Dim oResult As Node
For lIndex = mlLastFoundIndex + 1 To Me.TreeView1.Nodes.Count
If IsMatch(Me.TreeView1.Nodes(lIndex).Text) Then
Set oResult = Me.TreeView1.Nodes(lIndex)
mlLastFoundIndex = lIndex
Exit For
End If
Next lIndex
Set GetNextMatch = oResult
End Function
Private Sub txtSearch_Change()
mlLastFoundIndex = 0
End Sub
Rather than traversing the TreeView nodes collection by integer, you should use the Child and Next properties to accomplish what you're asking. The following code will print the children of the selected node in the order they appear in the TreeView control:
Private Sub Command3_Click()
If Not TreeView1.SelectedItem Is Nothing Then
PrintNodesInSortedOrder TreeView1.SelectedItem
End If
End Sub
Private Sub PrintNodesInSortedOrder(ParentNode As MSComctlLib.Node)
Dim Nod As MSComctlLib.Node
Set Nod = ParentNode.Child
Do While Not Nod Is Nothing
Debug.Print Nod.Text
Set Nod = Nod.Next
Loop
End Sub
I am attempting to place the hyperion/Essbase parent name next to the child member using the GetHypParent() function but my code below places a 0 (meaning a succesful function?) in column K vs the parent name its self. How (or is there a way) that i can place the parent name next to the child name?
Sub Example_HypGetParent()
Dim vtParent As Variant
For x = 9 To 20
ActiveSheet.Cells(x, 11) = HypGetParent(Empty, Trim(ActiveSheet.Cells(x, 4)), vtParent)
Next x
End Sub
The HypGetParent function returns an integer by design – it fills the vtParent variable with the value of the parent, assuming the call was successful. So theoretically you need something more like this:
For x = 9 To 20
Result = HypGetParent(Empty, Trim(ActiveSheet.Cells(x, 4)), vtParent)
ActiveSheet.Cells(x, 11) = vtParent
Next x
So I've seen a couple posts on this topic, but can't seem to find a way to get it to work. My goal is to create a Stacked Column Graph using VBA with the following characteristics:
Each column is based on data from a row (e.g. E6:P6, E7:P7, etc.).
Each "stack section" is each column in that row (located at E4:P4)
X Axes Labels are located in column A (e.g. A6, A7, etc.)
Y Axes Labels dynamic based on data (non specific).
Chart Title (which is the easy part - I got this).
Granted I also need the legend which shows the color key used by item 2.
This graph is one of three needed per report across 30+ reports that I generated via VBA from a raw data file. The last step to the reports is to make these graphs.
I am able to get stacked graph created, but the biggest problem is that as the data ranges above show, there are gaps in the data. This causes split sections in the graph as well as additional labels that I don't want. Essentially I don't know how to format the graph, and reading the Object Window that pops up from typing "ActiveChart." has only gotten me this far. If I know various formatting commands (alas I'm new to VBA with Excel), I can replicate it across all the charts that I need.
Dim data As Range
Set data = Range("A4:P12")
With Charts.Add
.ChartType = xlColumnStacked
.SetSourceData Source:=data, PlotBy:=xlColumns
.HasTitle = True
.ChartTitle.Text = "Weekly Report"
.Location Where:=xlLocationAsObject, Name:="Sheet1"
End With
Example of what I can make:
Output Graph
Side note about the blank data: The leftmost blank spot where a bar would be is the empty column D. Also I need to be able to edit the axes labels.
How about something like this:
Public Sub MakeGraph()
Dim ws As Excel.Worksheet
Dim data As Excel.Range
Dim x_axis_labels As Excel.Range
Dim series_names As Excel.Range
Dim sh As Excel.Shape
Dim ch As Excel.Chart
Dim I As Long
Set ws = Sheet1
Set data = ws.Range("E4:P12") ' Assumes the data are in E4:P12
Set x_axis_labels = ws.Range("A4:A12") ' Assumes the labels are in A4:A12
Set series_names = ws.Range("E2:P2") ' Assumes the labels are in E2:P2
Set sh = ws.Shapes.AddChart
Set ch = sh.Chart
With ch
.ChartType = xlColumnStacked
.SetSourceData Source:=data, PlotBy:=xlColumns
.HasTitle = True
.ChartTitle.Text = "Weekly Report"
.Axes(xlCategory, xlPrimary).CategoryNames = x_axis_labels
' Add series names
For I = 1 To .SeriesCollection.Count
.SeriesCollection(I).Name = series_names.Cells(1, I)
Next I
End With
Set ch = Nothing
Set sh = Nothing
Set series_names = Nothing
Set x_axis_labels = Nothing
Set data = Nothing
Set ws = Nothing
End Sub
Hope that helps
I take it your missing data would be a column in the range E6:P14? (I'm using E6:P14 because that's what you said first. Your code and #xidgel's later said E4:P12.)
Try this:
Sub MakeChart()
Dim rCats As Range
Dim rNames As Range
Dim rData As Range
Dim iCol As Long
Set rCats = ActiveSheet.Range("A6:A14")
Set rNames = ActiveSheet.Range("E4:P4")
Set rData = ActiveSheet.Range("E6:P14")
With ActiveSheet.Shapes.AddChart(xlColumnStacked).Chart
Do Until .SeriesCollection.Count = 0
.SeriesCollection(1).Delete
Loop
For iCol = 1 To rData.Columns.Count
If WorksheetFunction.Count(rData.Columns(iCol)) > 0 Then
' it's not blank
With .SeriesCollection.NewSeries
.Values = rData.Columns(iCol)
.XValues = rCats
.Name = "=" & rNames.Cells(1, iCol).Address(, , , True)
End With
End If
Next
End With
End Sub
I am using the following VBA Macro to delete all the pictures in a PowerPoint slide:
Public Function delete_slide_object(slide_no)
' Reference existing instance of PowerPoint
Set PPApp = GetObject(, "Powerpoint.Application")
' Reference active presentation
Set PPPres = PPApp.ActivePresentation
' Delete object in slide
Set PPSlide = PPPres.Slides(slide_no)
For Each PPShape In PPSlide.Shapes
If PPShape.Type = msoPicture Then
PPShape.Delete
End If
Next PPShape
Set PPShape = Nothing
Set PPSlide = Nothing
Set PPPres = Nothing
End Function
This code is deleting some but not all the pictures.After running this code 3 times , all the pictures get deleted. Where am i going wrong? Kindly let me know
When deleting items from a collection, you have to use a different iteration.
Try this:
Dim p as Long
For p = PPSlide.Shapes.Count to 1 Step -1
Set PPShape = PPSlide.Shapes(p)
If PPShape.Type = msoPicture Then PPShape.Delete
Next
This is because the collection is re-indexed when items are removed, so if you delete Shapes(2) then what was previously Shapes(3) becomes Shapes(2) after the deletion, and is effectively "skipped" by the loop. To avoid this, you have to start with the last shape, and delete them in reverse order.
I have been trying to declare variables inside a For loop for quite some time now, and I just haven't been able to find a way.
I'm attempting to create a new image (tile) for every time a certain number is encountered in a two-dimensioned array (Measuring 32x16). I may need to add in that I am using Visual Basic 6.
Currently I'm using the following code:
Option Explicit
Dim wCount As Integer
Dim hCount As Integer
Dim arrTiles(31, 15) As Integer
Private Sub Form_Load()
For wCount = 0 To 31 Step 1
For hCount = 0 To 15 Step 1
' -Declare variables
' -I.E. Dim NAME As Image
Next
Next
End Sub
However, the above code (Using Dim tile1 As Image) gives me an error whenever trying to access one of the properties of the newly added image (Such as tile1.Width).
Is there any way to declare a variable this way at run-time?
Sincerely
- Birjolaxew
You must assign a valid Image object to the Image variable before you try to access any properties of it. For example, this works fine:
For wCount = 0 To 31 Step 1
For hCount = 0 To 15 Step 1
' -Declare variables
Dim tile1 As Image
tile1 = Image.FromFile("c:/test.png")
Dim width = tile1.Width
Next
Next