Error setting PlotArea.Width in Excel, VBA (Excel 2010)

孤街浪徒 提交于 2019-11-27 23:15:23

Two solutions that seem to be working, neither is really as "elegant" as I'd prefer (I was hoping there would be a way to do this with selecting the chart or any part of it).

Option 1 - Select the plot area and then deselect it. This seems to be the most reliable/efficient solution.

With .PlotArea
    Application.ScreenUpdating = False
   .Select
    With Selection
        .Width = paWidth
        .Height = paHeight
        .Left = paLeft
        .Top = paTop
        ActiveSheet.Range("A1").Activate
    End With
    Application.ScreenUpdating = True
End With

Option 2 - disable error-handling in loop (this followed from Doug's link). This doesn't seem to be a very reliable or efficient method, and although it seems to work, I know that within that loop it is failing once on each of the properties before it successfully sets them on a subsequent pass.

With .PlotArea
    For pLoop = 1 To 5
        On Error Resume Next
        .Width = paWidth
        .Height = paHeight
        .Left = paLeft
        .Top = paTop
        On Error GoTo 0
    Next
End With

i had a similar problem . And its definitely an excel issue (having 2013).

With .PlotArea 
    .Select 'err if delete this line of code
    .Top = 0
    .Left = 0
    .width = 40
    .Height = 40 
End With

if you remove the .selectline, it will result in error on the next line. note that i am not working with a <with selectiondo stuff>. the .selectmakes it work, without using the selection, wich is obviously an excel bug (from previous versions?)

Hope your sheet and chart has the ability to get a width up to 640. If so try the explicit reference. Also suggest you to change width, height values to lower values and see how programme responds. Since you said, when you select it works,

  • that also means, your cht is wrapping the correct chart object - unless otherwise you selected the chart using ActiveChart.PlotArea.Width . Hence I guess explicit reference could do be a potential try out.

,

cht.PlotArea.Width = 640
cht.PlotArea.Height = 280
cht.PlotArea.Left = 30
cht.PlotArea.Top = 30

Further, check on Aspect Ratio lock or unlock. If none of these works, then add a chart into your sheet and use most simple chart formatting code to check on widht, height, left, top changes.


Update two

Let's try specifing chart type and setting up chart object in the second sub as well. I tried out in my end and it's working. Try the code with following changes.

Code: Calling this sub from the button showed in the sheet.

Option Explicit

  Public Sub EstablishChartObject()
  Dim mySheet As Worksheet
  Dim cObj As ChartObject

    Application.ScreenUpdating = False
    Application.StatusBar = "Chart is coming soon..."

    Set mySheet = Sheets(2) '-- set according to yours
    '-- create chart with some source data first, which you can change later
    Set cObj = mySheet.ChartObjects.Add(Left:=30, Top:=30, Width:=400, Height:=200)
    ChartSizeMedium cObj, "Integer", "Example Chart Title"

  End Sub


  'Subroutine to make a consistent size chart
  Private Sub ChartSizeMedium(chtObj As ChartObject, NumType As String, _
                                  Optional chtTitle As String)

  Dim myChart As Chart
  Dim s As Long

     Set myChart = chtObj.Chart '-- specify chart type
     myChart.SetSourceData Source:=Sheets(2).Range("B3:C12")  '-- set to what you have
     myChart.ChartType = xlXYScatterLines  '-- set to the type you want 
                                          'and make sure to **use correct properties**

        With myChart
            If .HasTitle Then
                .ChartTitle.Characters.Text = chtTitle
            End If

            'Create the default chart Legend
            If .HasLegend Then
                With .Legend
                    .Position = xlTop
                    .Font.Size = 11
                    .Font.Bold = True
                End With
            End If

            'Format the axes
            With .Axes(xlValue)
                .HasMajorGridlines = False
            End With

            'Format the size of the chart
            With .Parent
                .Width = 400 '-- change to yours
                .Height = 250 '-- change to yours
            End With

            With .PlotArea
                .Width = 300 '-- change to yours
                .Height = 180 '-- change to yours
                .Left = 30
                .Top = 30
            End With
    End With

    Application.ScreenUpdating = True
    Application.StatusBar = "Chart is Here!"

End Sub

Otput:

Make sure to use correct properties for each chart type. Note that above code doesn't delete any left over, old charts from your sheet.

.MajoreGridlines.Format.Lines.Visible fails. So set the .MajorGridlines = False to make sure you do not want to show the gridlines. Anything else you want to do can be done later. Just try with the changes to dimension initially.

Reference from : MSDN Gridlines property

I know this is old, and this solution seems bad, but it works. I only thought to do it as you mention that stepping through works.

Option Explicit

Sub chart()

Dim cObj As ChartObject
Dim sh As Worksheet

Set sh = ActiveSheet
Dim srs As Series
Set cObj = sh.ChartObjects.Add(Left:=30, Top:=30, Width:=740, Height:=300)
cObj.chart.ChartType = 57
Set srs = cObj.chart.SeriesCollection.NewSeries
    srs.Values = "={1,3,5,7,4}"
Application.Wait Now + TimeValue("00:00:01") '<~~ Added This line
With cObj.chart.PlotArea
    .Width = 100
    .Height = 280
    .Left = 30
    .Top = 30
End With
End Sub
David Zemens

EDIT: This seems to work for some chart types, but it was still failing for other chart types. I have continued to use the 5x loop with On Error Resume Next and that seems to be -- unfortunately -- the most "reliable" solution to-date.

Original: This is based on User2140261's suggested answer, above:

https://stackoverflow.com/a/16041640/1467082

Since the question was initially posted, the application now resides in PowerPoint, so I cannot use the Applicaiton.Wait. I had some intermittent errors with a 1-second pause, and 3-seconds was too much of a pause, so I built the following error trap. The same idea could be used in Excel in conjunction with Application.Wait.

It was this block of code that was giving me fits, so I added this error handling in Powerpoint to mimic the Application.Wait.

RetryChartDimensions:
On Error GoTo ErrChartDimensions
With .PlotArea
    .Width = paWidth
    .Height = paHeight
    .Left = paLeft
    .Top = paTop
End With
On Error GoTo 0

' More code
' more code

Exit Sub 'gracefully exit this subroutine before the error-handling.'

ErrChartDimensions:
Err.Clear
'Pause before setting the PlotArea dimensions:'
Dim wtTime As Double
Dim startTime As Long

'A maximum 3 second delay should be more than enough time.
If wtTime < 3 Then
    wtTime = wtTime + 0.5
    startTime = Timer
    While Timer < startTime + wtTime
        DoEvents
    Wend
End If
Resume RetryChartDimensions

End Sub

I don't have enough reputation to add a comment, so using the above solutions I have fixed my problem with Pie Charts in VB.Net 2010 and Excel 2013. xlLine charts never caused a problem, but my code would crash when the same code was ran against an xlPie chart on Excel 2013 (All was fine on Excel 2007).

My now working code:

    appExcel.Visible = False
    xlchart_for_96_Well_Plate_Source = appExcel.Charts.Add(After:=wkbExperiment_Details.Sheets(wkbExperiment_Details.Sheets.Count))
    appExcel.ScreenUpdating = False

    With xlchart_for_96_Well_Plate_Source
            .SetSourceData(Source:=wksData.Range(wksData.Cells(2, byteCharts_added), wksData.Cells(intUsed_Rows, byteCharts_added)), PlotBy:=Microsoft.Office.Interop.Excel.XlRowCol.xlColumns)
            .ChartType = objChart_Type
            .PlotArea.Select() 
            .PlotArea.Top = 2
            .PlotArea.Select()
            .PlotArea.Left = 2
            .SeriesCollection(.SeriesCollection.count).xvalues = wksData.Range(wksData.Cells(2, 1), wksData.Cells(intUsed_Rows, 1)).Value ' Scale - wavelength for line chart
            .SeriesCollection(.SeriesCollection.count).Values = wksData.Range(wksData.Cells(2, byteCharts_added + 1), wksData.Cells(intUsed_Rows, byteCharts_added + 1)).Value
            .SeriesCollection(.SeriesCollection.count).Name = wksData.Cells(1, .SeriesCollection.count + 1).value
    End With
appExcel.ScreenUpdating = True
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!