VBA legend and plot area resizing - excel

I have an Excel chart which changes on selections made in slicers.
I noticed that the plot area and the legend area change depending on the made selection.
I tried to fix the position and size for the plot area using vba, but this simply does not work unfortunately.
The plot area and the legend keep on resizing, causing the legend overlapping the plot area. Which I obviously do not want.
I have this code, placed in the worksheet page of the vba editor:
Option Explicit
Private Sub Chart_Calculate()
ChartObjects("grafiek 4").Activate
ActiveChart.PlotArea.Width = 637.783
ActiveChart.Legend.Left = 716.514
ActiveChart.Legend.Width = 176.735
ActiveChart.Legend.Height = 295.334
End Sub
having this code, I assumed the automatic resizing would be gone, but I saw the legend sometimes still overlaps te plot area.
Is there a solution which permanently fixes this problem?
Edit1:
Yesterday, I simply added a few parameters for the plot area. It seemed to work then. But now I tried again, and the legend is overlapping the plot area again.
I changed the code to:
Option Explicit
Private Sub Chart_Calculate()
ChartObjects("grafiek 4").Activate
ActiveChart.PlotArea.Top = 33.102
ActiveChart.PlotArea.Left = 67.1
ActiveChart.PlotArea.Width = 637.783
ActiveChart.Legend.Top = 7
ActiveChart.Legend.Left = 716.514
ActiveChart.Legend.Width = 176.735
ActiveChart.Legend.Height = 329.667
End Sub
So with 2 more paramters for the plot area.
edit2:
I have checked the legend properties in Excel. under 'options for legend' there is a checkbox: show legend without overlapping plot area (I do not know the exact english text).
This box is checked, but it does overlap the plot area.
Why is it impossible to achieve this? Having fixed sizes for the plot area and the legend should not be so hard.
edit 3:
I do have this routine now in my workbook:
Option Explicit
Private Sub Chart_Calculate()
ChartObjects("grafiek 4").Activate
With ActiveChart
With .PlotArea
.Top = 33.102
.Left = 67.1
.Width = 637.783
End With
With .Legend
.IncludeInLayout = True
.Position = xlLegendPositionRight
.AutoScaleFont = False
.Font.Size = 8
.Top = 5
.Left = 706.899
.Width = 179.735
.Height = 336.681
End With
End With
End Sub
Sub kopieergrafiek()
ActiveSheet.ChartObjects("Grafiek 4").Copy
End Sub
(including the suggestion in the comment below my post)
I does not seem to work. Does worksheet_change event perhaps works better?
edit 4:
I still do not have a solution for this issue. It already happens when the name of 1 of the legend items is to long to fit the space. And it also happens when there are to many items in the legend to fit in the space available.
I think there is no solution for this. Unless I could somehow tell excel to maximize the number of items in the legend. or to maximize the length of the series name.

I was having this problem myself with the legend resizing the plot area. I tried what Portland Runner suggested, only setting .Legend.IncludeInLayout to false (thus separating the legend from the plot area as he suggested, perhaps he made a typo?) and my plot area was no longer resized.

I also had this problem and found this answer. I found a fix that works for me. Not sure why exactly it works but I do these steps:
Set the legend position
Undock the legend (legend.includeLayout = false)
Resize the plot area to the size I wanted
Re-dock the Legend (legend.includeLayout = True)
Set the Legend.Left position
and after that the legend is correctly positioned and lined up.

I know this is an old thread, but since I had the same issue and was able to solve it, but did not really find the correct answer on this thread, I thought it would be good to post my solution. It is really important to refresh the pivotlayout, otherwise you will not see a difference in the Chart Legend. This will adjust the Legend so it will not overlap the plot area. It will also increase the size of the chart, so if you do not want that, you will need to use other code.
Sub AdjustChartLegendActiveSheet()
Dim j
For j = 1 To ActiveSheet.Shapes.count
If ActiveSheet.Shapes(j).Type = msoChart Then
ActiveSheet.Shapes(j).chart.Legend.IncludeInLayout = True
ActiveSheet.Shapes(j).chart.PivotLayout.PivotTable.PivotCache.Refresh
End If
Next j
End Sub

Related

Changing diagram size to specific size in mm with VBA

I have an existing Excel file I need to work with. It contains a line graph where measurement results are plotted. All the referencing is done via names. The graph is called "ChartResult".
Obviously Excel discriminates the graph area (the "outer") and the plot area (the "inner") where the graph is plotted. Please correct me if I'm wrong, also learning the preferred english nomenclature would be of great help.
My goal is to print the (page containing the) table so that the division/auxiliary lines have a specific distance from each other. My thinking was that if I define the scale of the axis (the max and min values) and define a size of the graph I would acheive this goal.
However in Excel I can only type in the size of the whole graph area, which is the outer thing, so not helpful when I want to define the size of the graph, the inner thing.
I started using VBA to acheive this but haven't been succesful:
Sub Groesse_eingeben()
ActiveSheet.ChartObjects("ChartResult").Activate
ActiveChart.SeriesCollection(1).Select
ActiveChart.PlotArea.Select
Selection.Left = 0
Selection.Top = 0
Selection.Width = 200
Selection.Height = 200
End Sub
This code is changing the size an position of the graph but not to what I expected it to be. Is the input of Selection.XY in pixels or mm? I naively assumed mm but my graph becomes smaller than 200x200 mm, around 60x60 mm.
Thank you!
Chris
System:
Microsoft® Excel® 2016 MSO (Version 2204 Build 16.0.15128.20128)
Win10 Pro 21H2
Update:
Ok, the input size is points. But how to specify the exact size of the graph?
On the screenshot there are two dotted borders: One, the inner, is the actual size of the visible graph the other is the size of the graph object. To cause more confusion: Both are within the graph area, which I called "outer" area above :)
How can I input the exact numbers for the actual visible graph?
You can control the outer width of the chart (ChartObject) with the .Width property, and the inner width of the chart with the .Chart.PlotArea.Width property.
Here is a sub that takes a chart and widths as inputs, and updates the chart:
Private Sub SetChartWidths(Ch As ChartObject, OuterWidth As Long, InnerWidth As Long)
' Set the outer width of the chart
Ch.Width = OuterWidth
' Set the inner width (plot area width)
Ch.Chart.PlotArea.Width = InnerWidth
End Sub
EDIT START
And here is how you can use the sub:
Private Sub UseSubroutine()
' Store the chart object in a variable
Dim LineChart As ChartObject
Set LineChart = ThisWorkbook.Sheets("Sheet1").ChartObjects(1)
' Run the sub
SetChartWidths Ch:=LineChart, OuterWidth:=200, InnerWidth:=150
End Sub
If you're having trouble using the SetChartWidths sub, and it is in a different Module than the code you're calling it from, you can remove the Private from the front to change the Scope of the sub.
EDIT END
As for what widths to use, that will be up to you.

Change chart height without resizing plotArea

I am trying to resize an excel chart with VBA.
Is it possible to change ActiveChart.ChartArea.Height without affecting the size of the PlotArea? Whenever I attempt to change the chart height it looks like the plot area is automatically resized, which is an undesired outcome.
I have tried the following sequence, when downsizing a graph:
Changing plotarea to fixed desired height;
Changing chart height to fixed desired height;
Changing plotarea to fixed desired height;
This sequence does not yield expected results, as (1) the chart is not changed to specified height, and (2) the plotarea height is output correctly, but its positioning within the chart (.InsideTop) has changed.
Please, test the next way of dealing with a chart dimensions. The scenario involves the next process: firstly memorizing the PlotArea dimensions (Height/Width), then play with the chart (Object) dimensions, reset the PlotArea ones and set its Position to Automatic. Excel tries guessing what you want accomplishing and it looks/is more probable that both chart elements to be modified proportionally:
Sub testActiveChartDimensions()
Dim ch As Chart, plHeight As Double, plWidth As Double
Set ch = ActiveChart 'plays with a selectded chart
plHeight = ch.PlotArea.height: plWidth = ch.PlotArea.width 'memorize the plot area dimensions
ch.Parent.height = ch.Parent.height * 2: ch.Parent.width = ch.Parent.width * 2 'resize the chartObject
ch.PlotArea.height = plHeight: ch.PlotArea.width = plWidth 'reset the initial dimensions for plot area
' you can set any other dimensions (just to be lower than the new chart dimensions...)
ch.PlotArea.Position = xlChartElementPositionAutomatic 'center it on the chart object
End Sub

How to set or modify the font size from a chart embedded in a userform

I'm programming an userform to show a graph with data stored in a range of cells, but when the graph shows it is so small and it gets impossible to read, and it shows another label with "series 2" even when i didn't added it.
I tried changing the properties of the image box, from "0 fmPictureSizeModeClip to fmPictureModeZoom but it only makes it blurry, i tried to modify my code adding:
MyChart.Parent.Width = 1200
MyChart.Parent.Height = 780
But it only the bars get big and the labels and title keeps small, and being unable to read.
Set MyChart = ActiveSheet.Shapes.AddChart(xlColumnClustered).Chart
MyChart.Parent.Width = 1200
MyChart.Parent.Height = 780
MyChart.SeriesCollection.NewSeries
MyChart.SeriesCollection(1).Name = ChartName
MyChart.SeriesCollection(1).Values = ChartData
MyChart.SeriesCollection(1).XValues = ActiveSheet.Range("K32:K43")
This is the userform after adding:
MyChart.Parent.Width = 1200
MyChart.Parent.Height = 780
and this is before it, as you may see the text is illegible, the name of the chart in the screenshot disappeared but i corrected the code and now it appears but just as small as the other text in the chart
If complementary info needed i will gladly provide it,
any help is appreciated.
I figured out the answer.
MyChart.Axes(xlCategory).TickLabels.Font.Size = 20
MyChart.Axes(xlValue).TickLabels.Font.Size = 20
MyChart.Legend.Font.Size = 20
MyChart.ChartTitle.Font.Size=24

Remove frame borders in userform

I am trying to remove the border of frame that has a lot of check boxes and I tried 'borderstyle 0 - frmborderstylenone' in the frame properties and it is not working. I have shown the frame border in the picture. I have many of these frames in a userform and each of these frames has at least 5 check boxes. kindly help me out
You may be surprised to learn the picture you provided does not have a Border. What you see is the SpecialEffect property set to fmSpecialEffectSunken.
You can set the property to fmSpecialEffectNone to remove it. It can be set manually in the project properties window or via code.
Setting the Border property to fmBorderStyleSingle while using a special effect will set fmSpecialEffectNone because borders are special effects are mutually exclusive. Enabling one will disable the other because you cannot use both at the same time. This is why setting and then removing the border works.
Following TheJeebo hint, setting the frame properties from code, this doesn't work:
Set myForm = New Userform
Set frm = myForm.Controls.Add("Forms.Frame.1", "Frame1", True)
With frm
.BorderStyle = 0
The frame border still there when the UserForm is displayed, but surprisingly this does work:
Set myForm = New Userform
Set frm = myForm.Controls.Add("Forms.Frame.1", "Frame1", True)
With frm
.BorderStyle = 1
.BorderStyle = 0
no border now.

How to fix an Excel listbox that can't scroll the last element into view

A killer problem I've had in excel UIs since as long as I can remember, is with listbox scrolling.
When you have more elements in a listbox that can be displayed, a scoll bar will appear. In certain conditions, however, scrolling the bar all the way to the bottom of the list and releasing it, will "jump" the bar a notch upwards, and you won't be able to see the last item in the list. This is illustrated here:
There are many forum posts presenting this issue, and the solution has always been "Set the integral height property to false, and then set it to true again." What this does is slightly resize the listbox so that it the height is rounded to the height of a single row, and then no items are left hidden.
With lstbox
.IntegralHeight = False
.Height = myHeight
.IntegralHeight = True
End With
There are certain cases, however, where this does not work. If you are:
Programatically setting the height of your listbox
NOT using simple listbox selection (fmMultiSelectSingle)
Then simply setting integral height to false and then true after or between changes to height will make an adjustment to the height of your listbox, but when you go to scroll down, the problem will remain - the last item cannot be seen.
The key to this frustrating question is that while everyone else on the internet is confirming that the 'integralHeight' solution works for them, these very special cases are frustrated wondering why it doesn't work for them. So how do they get their fix?
Something I had to discover for myself, and which cannot be found anywhere else (which is why I'm posting it here), is that this problem had the added dimension of being dependent on the selection method. While I cannot fathom how the way the scroll bar works is related to not only the height and integral height property, but also the .MultiSelect property, I have found that it is.
When the .IntegralHeight method shown above does not work, the following method somehow does:
With lstbox
.IntegralHeight = False
.Height = myHeight
.IntegralHeight = True
.MultiSelect = fmMultiSelectSingle
.MultiSelect = fmMultiSelectExtended
End With
By simply changing the .MultiSelect property to fmMultiSelectSingle, and then restoring it back to the selection style desired, the height of the listbox will be automatically adjusted by the .IntegralHeight property to a slightly different height than when these actions aren't performed - the difference results in the scroll bar working correctly:
I hope the discovery of this special case and more precise workaround saves someone the hours of frustration and experimentation I had to go through.
i know this is very old post.
but i've been through a lot to fix this problem, so i just wanna share my tip. :)
first of all,
integralheight method doesn't work when worksheet zoom level is not 100%.
it will change listbox height and width, location, etc. (even if you set object property 'doesn't move or reseize with cell')
and when you try to take it its original size and location with code to fix this, this time its last item can't be seen
my tip is simple.
there's combination between font size and listbox height.
if your font size is 6-10(arial, regular), listbox height goes well with multiples of 12.75 (btw my list box style is 1 : ListStyle, 1-fmListStyleOption. it could be different with style 0)
as long as height is same with these multiples of 12.75, there will be no problem.
in case of font size 12(arial, regular), it's multiples of 13.55
so if there's no restiction about listbox size in your project, just resizing it slightly depending on your font size gives more comfort. :)
I had to anchor the position since my ListBox was walking across the page:
With ListBox1
.IntegralHeight = False
.IntegralHeight = True
.Height = 45
.Width = 69
.Top = 0
.Left = 1255.5
End With
With lstbox
`.Height = myHeight`
`.MultiSelect = fmMultiSelectExtended`
`.MultiSelect = fmMultiSelectSingle`
End With
This worked for me. No need of setting Integral height property
In my case the solution was this method:
with listbox
.IntegralHeight = False
.Height = myHeight
.Width = myWidth
.IntegralHeight = True
.Height = myHeight
.Width = myWidth
end with
Enjoy.
found ridiculously simple way to resolve this issue. adjust your height up or down a little bit so bottom line of list box is between check boxes, then you can scroll down to last item even if IntegralHeight is set to false
Thanks Alain. Your fix worked well for me.
I found a subsequent problem related to the height of the ListBox when resized, that it varied in an unpredictable way depending on the initial height. The resized height was different again when displayed on another machine with 125% text scaling. For example, if I set a height between 358 and 370, the resized height is either 370.65 or 371.4 on my machine but on the machine with 125% text scaling, it is 360.1, 370.25 or 380.45. With such large variability, the result was that the ListBox could obscure other controls below it.
The fix was to start with the maximum height I wanted and reduce the initial height until the resized height was less than the maximum height I wanted. I do this whenever I display that ListBox.
Hmax = 372 'Target Height
H1 = Hmax
With SteelForm.Controls.Item("ListBox1")
Do
H1 = H1 - 1
.IntegralHeight = False
.Height = H1
.IntegralHeight = True
.MultiSelect = fmMultiSelectSingle
.MultiSelect = fmMultiSelectExtended
DoEvents
Loop Until .Height < Hmax
End With
What I've seen in the past on forums is just adding an extra blank row to your list box. That should do it.
Just set the Integral Height property to True

Resources