Find textbox in a group of shapes (VBA 6.3) - excel

I am using VBA 6.3. In Excel I have a chart - left y axis on it and numbers. When I copy the Chart to powerpoint and degroup it, I leave the y axis only with the TextBoxes and the axis alone. Now I would like to obtain the minimum and maximum numbers beside the axis. First I tried to detect the TextBoxes it should be msoTextBox value 17. But when I checked the type number is 378*... I could not find out what is it (using google search). I need to obtain the two numbers and length of the axis line (so I can calculate the ratio y_length/(max-min) ).
This is the code sofar.
Sub GetMinMax()
Dim YAxisMinMax() As Integer
With ActiveWindow.Selection
If (.Type = ppSelectionShapes) And (.ShapeRange.Type = msoTextBox) Then
Else
MsgBox "Failed"
Exit Sub
End If
End With
End Sub
Rhe result - The Message is Failed. It did not found the TextGroup with number.
*Edit: I have found, that the type is different for every "text box". However the name of the shape is "rectangle", not a text box". It looks like text box, because it has text inside it.

So far, this what I have done:
Option Explicit
Private Type T_HORIZONTAL_LINE
ShortLineLeft As Integer
ShortLineTop As Integer
Length As Integer
isFound As Boolean
End Type
Private Type T_VERTICAL_LINE
ShortLineLeft As Integer
ShortLineTop As Integer
Length As Integer
isFound As Boolean
End Type
Sub LookForAxis()
Dim Horizontal As T_HORIZONTAL_LINE
Dim Axis As T_VERTICAL_LINE
Dim YAxisMinMax(2) As Integer
Dim OldMinMax(2) As Integer
Dim Value As Integer
Dim Ratio As Single
Dim Text As String
Dim Sh As Shape
With ActiveWindow.Selection
If (.Type = ppSelectionShapes) And (.ShapeRange.Type = msoGroup) Then
For Each Sh In .ShapeRange.GroupItems
If Sh.Type = msoLine Then
If (Axis.isFound) And (Horizontal.isFound) Then
ElseIf (Sh.Width < Sh.Height) And (Not Axis.isFound) Then
Axis.Length = Sh.Height
Axis.ShortLineLeft = Sh.Left
Axis.ShortLineTop = Sh.Top
Axis.isFound = True
ElseIf (Sh.Width > Sh.Height) And (Not Horizontal.isFound) Then
Horizontal.Length = Sh.Width
Horizontal.ShortLineLeft = Sh.Left
Horizontal.ShortLineTop = Sh.Top
Horizontal.isFound = True
End If
ElseIf (Sh.Type = msoAutoShape) And (Sh.HasTextFrame = msoTrue) Then
Text = Sh.TextFrame.TextRange.Text
Value = CInt(Text) ' Possibly: CLng()
If Value < OldMinMax(1) Then
OldMinMax(1) = Value
ElseIf Value > OldMinMax(2) Then
OldMinMax(2) = Value
End If
End If
Next Sh
Ratio = Axis.Length / (OldMinMax(2) - OldMinMax(1)) ' Axis length div. axis range
Else
MsgBox "You have not selected an OBJECT in PowerPoint to dimension."
Exit Sub
End If
End With
End Sub
Notice: I have first placed all the axis lines and rectangles with TextFrame to one group to make it easy.

Related

How can I change the shape size of a shape by clicking another shape?

I have multiple shapes that when clicked it's doing things in my Excel sheet (my code below).
But apart from these things I want to change the size of a shape that is positioned 2 cells to the right of the shape I'am clicking.
How can I do this without referring to the name of the shape I want to resize?
This is my code.
Sub ArrowClick()
With ActiveSheet.Shapes(Application.Caller).TopLeftCell
.EntireRow.Borders(xlEdgeBottom).LineStyle = xlNone
With .EntireRow.Offset(1, 0).Resize(9)
.EntireRow.Hidden = Not .Hidden
End With
End With
End Sub
Please, use the next way. It will select the shape on the second column of the clicked shape row and double its width:
Sub ArrowClick()
Dim nextSh As Shape
Const sizeW As Double = 45 'use there your usual real width
Const sizeH As Double = 14 'use there your usual real height
With ActiveSheet.Shapes(Application.Caller).TopLeftCell
.EntireRow.Borders(xlEdgeBottom).LineStyle = xlNone
With .EntireRow.Offset(1, 0).Resize(9)
.EntireRow.Hidden = Not .Hidden
End With
Set nextSh = findNextSh(.Offset(0, 2).Address)
If Not nextSh Is Nothing Then
nextSh.placement = xlMove 'set the placemeny property to `Move but don't size with cells
If nextSh.width = sizeW Then
nextSh.width = sizeW * 2 'use here what size you need for changing the initial sizes
nextSh.height = sizeH * 1.2
Else
nextSh.width = sizeW: nextSh.height = sizeH
End If
End If
End With
End Sub
Function findNextSh(strRange As String) As Shape
Dim sh As Shape
For Each sh In ActiveSheet.Shapes
If sh.TopLeftCell.Address = strRange Then
Set findNextSh = sh: Exit Function
End If
Next sh
End Function

How to create and call a function in VBA?

I am trying to create my first function or procedure in VBA. Basic types which I use in the code:
Private Type T_DATA_COLUMN_INFO
count As Integer
positiveColumnsColors(2) As Long ' decimal values from Hex
negativeColumnsColors(1) As Long
excludeColumnsColors(1) As Long
zeroTop As Integer ' position of zero, the Top property of zero rectangle
dataWidth As Integer
negativeDataHeight As Integer
positiveDataFound As Boolean
negativeDataFound As Boolean
End Type
' All is on horizontal axis except negativeValueY
Private Type T_COLUMN_RANGES
Xmin As Integer ' (Left) actually
Xmid As Integer ' middle position
Xmax As Integer ' Left + Column width
Xgap As Integer ' Gap between column rectangles
Xpitch As Integer ' Gap between colRanges()(1).mid and colRanges()(2).mid
negativeValueY As Integer ' Top+Height
Q1Y As Integer
Q2Y As Integer ' position of median
Q3Y As Integer
initiated As ENUM_INITIATED
End Type
What I have currently is not a function but procedure:
Sub SetColumnRanges(Sh As Shape, i As Integer)
colRanges(0).Width = 0
End Sub
But best would be if it would return variable 'passed boolean'
My code starts like this (shorted version):
Sub LookForAxis()
Dim colRanges() As T_COLUMN_RANGES
Dim i As Integer
Dim Sh As Shape
Dim passed As Boolean
ReDim colRanges(1 To 1) As T_COLUMN_RANGES
colRanges(1).initiated = 0
...
With ActiveWindow.Selection
If (.Type = ppSelectionShapes) And (.ShapeRange.Type = msoGroup) Then
For Each Sh In .ShapeRange.GroupItems
If (Sh.Name Like "Rec*") Then
For i = 1 To dataInfo.count
If Not passed Then ' If the array ...
' code skipped
' HERE I TRY TO CALL THE PROCEDURE OR FUNCTION... best if passed is returned for function:
SetColumnRanges Sh, i
Now the code to be placed in the function:
If Sh.Fill.ForeColor.RGB = dataInfo.positiveColumnsColors(1) Then
colRanges(i).initiated = colRanges(i).initiated Or columns_initiated_positive
If colRanges(i).Q1Y = 0 Then
colRanges(i).Q3Y = 0
colRanges(i).Q2Y = Sh.Top
colRanges(i).Q1Y = (Sh.Top + Sh.Height) * -1
ElseIf colRanges(i).Q1Y < 0 Then
If colRanges(i).Q1Y * -1 < Sh.Top + Sh.Height Then
tempInt = colRanges(i).Q2Y * -1
colRanges(i).Q3Y = colRanges(i).Q2Y ' Make the old value positive
colRanges(i).Q2Y = tempInt ' Make the old value positive
colRanges(i).Q1Y = Sh.Top + Sh.Height
Else
' Sh.Name = "Q3"
colRanges(i).Q3Y = Sh.Top + Sh.Height
colRanges(i).Q1Y = colRanges(i).Q1Y * -1 ' Make the old value positive
End If
End If
ElseIf Sh.Fill.ForeColor.RGB = dataInfo.negativeColumnsColors(1) Then
' Sh.Name = "Negative"
colRanges(i).initiated = colRanges(i).initiated Or columns_initiated_negative
End If
So colRanges and SH should be used in the function.
Error I get is:
Byref argument type mismatch
What am I doing wrong and how to fix it correctly?
you question format is a bit messed up which makes it complicated to read so if you can update it I could be more precise but calling a function works like this:
Sub test()
MsgBox test2("hi")
Dim var As String
var = test2("hi")
MsgBox var
End Sub
Function test2(var As String) As Boolean
test2 = True
End Function
you must make sure the type of the vars you are passing to your function are of the same type as the ones declared in your function (e.g. passing "hi" to "string" is ok but this would not work if var would be of type long in the function.
at the end of your function you send the result back by using the function name => "Test2 = output of your function you want to send back".

Get the number of the active series in an active chart

I am trying to make a fairly easy macro to activate the next series in an already active chart. (my main macro contains all the formatting stuff).
Problem with this coding, is that i am not able to assign the current active series (already selected in the graph in excel). In a graph with n series (SeriesCollection.Count = n) I want to go from x, to x+1 and if x=n i want to go back to series 1 (so the for/next included here is not necessary if I get the macro to work as intended).
Sub NextButton_Click()
Dim cht As Chart
Set cht = ActiveChart
If cht Is Nothing Then
MsgBox "Select a chart."
Exit Sub
End If
With cht
For SrsIndx = 1 To .SeriesCollection.Count
.SeriesCollection(SrsIndx).Select
Next SrsIndx
End With
End Sub
For Simple graphs, just use PlotOrder: If you are not using a Combo Chart (i.e. not mixing Line and Bar charts, and not using the Secondary Axis), then you can just use the following code:
IIF(TypeName(Selection)="Series", Selection.PlotOrder, -1)
This will return -1 if you do not have a Series selected.
However, this is actually the order within the ChartGroup - the conditions above were for when there is only 1 ChartGroup on the Chart.
Otherwise, try using Name and a loop:
Function ActiveSeriesNumber(ThisSeries AS Series) AS Long
Dim ThisChart AS Chart, TestNumber AS Long
ActiveSeriesNumber = -1
On Error GoTo FunctionError
Set ThisChart = ThisSeries.Parent.Parent 'Object Model Is Chart.ChartGroup.Series
For TestNumber = 1 to ThisChart.SeriesCollection.Count
If ThisChart.SeriesCollection(TestNumber).Name = ThisSeries.Name THen
ActiveSeriesNumber = TestNumber
Exit Function
End If
Next TestNumber
FunctionError:
On Error GoTo -1
End Function
Use this by calling ActiveSeriesNumber(Selection)
Here's the General Idea. Step through that code and you can see each series gets selected. You'll need add some object validation as this assumes the selected object is a Series.
Sub CycleSeries()
Dim MyObject As ChartObject
Dim MyChart As Chart
Dim SerCol As SeriesCollection
Dim SelSeries As Series
Dim indexSeries As Series
Dim ChartSheet As Worksheet
Dim x As Integer
Set ChartSheet = ThisWorkbook.Sheets(1)
Set MyObject = ChartSheet.ChartObjects(1)
Set MyChart = MyObject.Chart
Set SerCol = MyChart.SeriesCollection
Set SelSeries = Excel.Application.Selection
For x = 1 To SerCol.Count
Set indexSeries = SerCol(x)
If indexSeries.Name = SelSeries.Name Then
If (x = SerCol.Count) Then
Set SelSeries = SerCol(1)
SelSeries.Select
Exit For
Else
Set SelSeries = SerCol(x + 1)
SelSeries.Select
Exit For
End If
End If
Next x
End Sub

Can I reference an object using a string?

So my code looks like this:
Dim i As Integer
Dim labelnum As String
For i = 1 To 81
labelnum = "Label" & i
If "labelnum".Caption = Label1.Caption Then
"labelnum".BackColor = Label1.BackColor
End If
Next i
I want to loop through 81 labels to check to see if the caption in that one is the same as the one I have selected. Is there something else I can put where it says "labelnum"?
I'm practicing and trying to make sudoku through VBA. I want to highlight the box I have selected and highlight all other squares on the board that have the same number.
Thanks!
In a Worksheet, a Label is a Shape Object, so you can use the Shapes collection:
Dim i As Integer
Dim shpLabel As Shape
For i = 1 To 81
Set shpLabel = Sheet1.Shapes("labelnum" & i)
If shpLabel.Caption = Label1.Caption Then
shpLabel.BackColor = Label1.BackColor
End If
Set shpLabel = Nothing
Next i
In a UserForm, a Label is a Control Object, so you can use the Controls collection:
Dim i As Integer
Dim ctrlLabel As Control
For i = 1 To 81
Set ctrlLabel = Me.Controls("labelnum" & i)
If ctrlLabel.Caption = Label1.Caption Then
ctrlLabel.BackColor = Label1.BackColor
End If
Set ctrlLabel = Nothing
Next i

C# Excel Chart Change color

I am trying to change the line color of the chart series to None. I tried setting the color and the marker property but the program errors out.
My code:
Excel.ChartObjects _ChartObjects = (Excel.ChartObjects)(oSheet1.ChartObjects(Missing.Value));
Excel.ChartObject _ChartObject = _ChartObjects.Add(170, 0, 400, 300);
Excel.Chart _Chart = _ChartObject.Chart;
Excel.Range oRng1;
oRng1 = oSheet1.get_Range("A1","E55");
_Chart.SetSourceData(oRng1, Excel.XlRowCol.xlColumns);
_Chart.ChartType = Microsoft.Office.Interop.Excel.XlChartType.xlLineMarkers;
oWB.ShowPivotChartActiveFields = true;
//_Chart.ChartTitle.Font.Size = 12;
_Chart.SetElement(Microsoft.Office.Core.MsoChartElementType.msoElementDataTableWithLegendKeys);
_Chart.DataTable.Font.Size = 6;
oWB.ShowPivotChartActiveFields = false;
_Chart.SetElement(Microsoft.Office.Core.MsoChartElementType.msoElementPrimaryValueAxisTitleRotated);
_Chart.SetElement(Microsoft.Office.Core.MsoChartElementType.msoElementLegendNone);
//_Chart.Legend.Delete();
_Chart.SetElement(Microsoft.Office.Core.MsoChartElementType.msoElementPrimaryValueAxisTitleNone);
_Chart.Location(Excel.XlChartLocation.xlLocationAsNewSheet, "Tax Weekly Term-Chart");
Excel.SeriesCollection seriesCollection = (Excel.SeriesCollection)_Chart.SeriesCollection(Type.Missing);
Excel.Series series = (Excel.Series)seriesCollection.Item(4);
Need code to set the color of the series to None.Any suggestions would be useful.
This code can set the colours of the slices of all the pie charts in my spreadsheet based on each slice's legend's label:
Sub SetPieChartColours()
' Iterates through all pie charts in the dashboard and apply colours to the appropriate legends
' Colour indices:
' Passed (Green) 10
' Not Completed (Yellow) 19
' No run (Blue) 37
' Failed (Maroon) 18
' Failed Issue (Pink) 24
' Failed Defect (Red) 3
Dim savePtLabel As String
Dim ThisPt As String
Dim NumPoints As Integer
Dim x As Integer
Dim pie As ChartObject
For Each pie In ActiveSheet.ChartObjects
' Check that the current chart object is a pie chart
If pie.Chart.ChartType = xlPie Then
NumPoints = pie.Chart.SeriesCollection(1).Points.Count
For x = 1 To NumPoints
' Save the label currently attached to the current slice
If pie.Chart.SeriesCollection(1).Points(x).HasDataLabel = True Then
savePtLabel = pie.Chart.SeriesCollection(1).Points(x).DataLabel.Text
Else
savePtLabel = ""
End If
' Assign a new data label of just the point name
pie.Chart.SeriesCollection(1).Points(x).ApplyDataLabels Type:= _
xlDataLabelsShowLabel, AutoText:=True
ThisPt = pie.Chart.SeriesCollection(1).Points(x).DataLabel.Text
' Based on the label of this slice, set the color
Select Case ThisPt
Case "Failed-Defect"
pie.Chart.SeriesCollection(1).Points(x).Interior.ColorIndex = 3
Case "Failed-Issue"
pie.Chart.SeriesCollection(1).Points(x).Interior.ColorIndex = 24
Case "Failed"
pie.Chart.SeriesCollection(1).Points(x).Interior.ColorIndex = 18
Case "No Run"
pie.Chart.SeriesCollection(1).Points(x).Interior.ColorIndex = 37
Case "Not Completed"
pie.Chart.SeriesCollection(1).Points(x).Interior.ColorIndex = 18
Case "Passed"
pie.Chart.SeriesCollection(1).Points(x).Interior.ColorIndex = 10
Case Else
' Aroo! The label of the current slice doesn't match any expected labels
pie.Chart.SeriesCollection(1).Points(x).Interior.ColorIndex = 1
End Select
' Return the label to it's original state
pie.Chart.SeriesCollection(1).Points(x).ApplyDataLabels Type:=xlDataLabelsShowNone, AutoText:=True
Next x
End If
Next
End Sub
And this code can set barchart colours:
Sub SetBarChartColours()
Dim savePtLabel As String
Dim ThisPt As String
Dim NumPoints As Integer
Dim x As Integer
Dim bar As ChartObject
For Each bar In ActiveSheet.ChartObjects
If bar.Chart.Name = "Dashboard Chart 5" Then
NumPoints = bar.Chart.SeriesCollection.Count
For x = 1 To NumPoints
MsgBox bar.Chart.Legend.LegendEntries(x).LegendKey.Interior.ColorIndex
Next x
End If
Next
End Sub
Maybe could help you!

Resources