I am attempting to copy a shape group which contains some charts as a high resolution picture. To achieve the high resolution, I use the options Appearance:=xlPrinter and Format:=xlBitmap.
Run-time error '1004' Application-defined or object-defined error
The code I am using to do this is below
ws.Shapes.Range(Array("Chart 1", "Chart 2")).Group.Name = "temp_group"
With ws.Shapes("temp_group")
.CopyPicture Appearance:=xlPrinter, Format:=xlBitmap
.Ungroup
End With
If I just remove the Format:=xlBitmap or change it to Format:=xlPicture, it works fine. The MSDN help shows xlBitmap as an option and I have tried just using 2 but that gives the same error.
If I try the same thing on a single chart, it works just fine.
ws.ChartObjects("Chart 1").Chart.CopyPicture Appearance:=xlPrinter, Format:=xlBitmap
What is the best way to copy multiple charts as a high resolution picture? I would like to avoid saving them because I need to copy/paste multiple groups of up to 30 charts for exporting to OneNote.
Edit:
After some additional testing, it turns out that I can use xlBitmap if the appearance option is set to xlScreen instead of xlPrinter. However, the resolution is still pretty terrible. This is very frustrating since just copy/pasting these same charts manually gives very nice clear pictures but for some reason VBA just ruins it. VBA is required though since this would be a very time consuming process otherwise.
shape.copypicture work's fine in excel 2016. The error is in office 360.
I was facing the same problem in my app. Here is the solution:
If you want to copy an object of type MsoShapeType.msoChart or MsoShapeType.msoPicture do this trick:
shape.ScaleHeight(2.5f, MsoTriState.msoFalse);
shape.ScaleWidth(2.5f, MsoTriState.msoFalse);
shape.Copy();
shape.CopyPicture(Excel.XlPictureAppearance.xlScreen, Excel.XlCopyPictureFormat.xlPicture);
shape.ScaleHeight(0.4f, MsoTriState.msoFalse);
shape.ScaleWidth(0.4f, MsoTriState.msoFalse);
where shape is of course your object.
First, you need to scale up the object (scaling is loseless up to orginal size of the image or maximum size of the chart, which is just 400% zooming). Then, you use CopyPicture() method with mentioned parameters, preceed with Copy()*.The last thing to do is to scale down (or not, if you won't save this sheet) the object.
*Copy() is used here to eliminate common and random error
System.Runtime.InteropServices.COMException (0x800A03EC): CopyPicture method of range class failed
If you open any Excel sheet, you will see some copy configurations:
link, because I can't add images yet
Common copy is just (xlScreen, xlBitmap);
Good quality copy is xlScreen, xlPicture) and, depending on installed printer driver, (xlPrinter) and (xlPrinter, xlPicture);
Related
I have a macro that is intended to copy a chart from excel into a word document in the same way as manually copy and pasting using "Keep Source Formatting and Embed Workbook." Below is the code that, to my understanding, should accomplish this.
Set reductionChart = graphWorksheet.ChartObjects("reduction")
reductionChart.Copy
masterReport.Paragraphs.Last.Range.PasteAndFormat wdChart
graphWorksheet is the worksheet that contains the graphs, masterReport is the word document.
The issue I am having is error 4605 command not available on the PasteAndFormat line. I happened to discover that manually copying the graph then running the line worked without issue. Thinking that maybe right clicking copied in a different way than .copy so I record a macro of the action and ended up with:
ActiveSheet.ChartObjects("Reduction").Activate
ActiveChart.ChartArea.Copy
Even substituting this in the error still occurs. What is happening here?
After some additional testing I am thinking that possibly when using .copy the chart is sort of only stored within excel and not the clipboard so when paste and format looks for something it see an empty clipboard and has an error, but right clicking copy stores it to the clipboard hence why is available still even after I run ActiveChart.ChartArea.Copy again.
I've attempted to create new workbook with a single sheet and chart. Also tried using late binding instead on the off chance that did something. This is the full code still giving the same issue
Sub test()
Dim masterWord As Object
Dim masterReport As Object
Set masterWord = CreateObject("Word.Application")
Set masterReport = masterWord.Documents.Add
masterWord.Visible = True
ThisWorkbook.Worksheets(1).ChartObjects("Chart 1").Copy
masterReport.Paragraphs.last.Range.PasteAndFormat wdChart
End Sub
After much testing this is the best workaround I'm managed to figure out.
reductionChart.Chart.ChartArea.Copy
masterReport.Paragraphs.Last.Range.PasteAndFormat wdFormatOriginalFormatting
masterReport.InlineShapes(masterReport.InlineShapes.Count).LinkFormat.BreakLink
wdFormatOriginalFormatting and wdPasteDefault both work and don't seem to make a difference to the outcome as far as I have seen.
This has one issue that I've found which is that on ActiveDocument.Fields.Update an information box will popup warning that the linked file is unavailable. This will occur for each unlinked item. I attempted to use Application.DisplayAlerts = False but this did not prevent the popup. This may come back to bite me, but I simply removed this line as it was unnecessary for my purposes.
I want to insert error bars into a clustered column chart in excel using macros. Whenever I do, an error is thrown.
I have a much larger program that takes and sorts data into a couple column charts, and I want to add error bars to them. In an attempt to troubleshoot, I stripped the program way back to just the part that adds the error bars in a separate sheet (code below). I made a simple column chart, selected it and tried to run the program, but it threw an Application Defined error.
Then I tried recording a macro, and that also failed (with a "Method SetElement of Object _Chart Failed" error).
I've Googled around a bit, and found next to nothing (only examples of how to use my first method, close to exactly the same as mine), but also I am relatively new to VBA and might just not know the correct words to google.
Here is my code:
'The code that I had written
Sub AddErrorBars()
'Adds error bars (Standard deviation) to selected chart
ActiveChart.SeriesCollection(1).ErrorBar Direction:=xlY, _
Type:=xlErrorBarTypeStDev, Include:=xlBoth
End Sub
'The code generated by recoring a macro
Sub AddErrorBarsV2()
'Adds error bars (Standard deviation) to selected chart
ActiveChart.SetElement (msoElementLineHiLoLine)
End Sub
One odd thing, the Include enum in first sub (xlBoth) was listed as xlErrorBarIncludeBoth in the MO documentation website, but the listed value is 1, which is the value of xlBoth according to the debugger, xlErrorBarIncludeBoth is empty. Using xlNone doesn't spit out an error, but also doesn't generate error bars. Ive also tried changing the Direction, but that doesnt seem to help.
Is there something I am doing wrong, or perhaps is it the way my data is formatted? Does anyone else seem to have the same issue?
If you have the chart selected, then ActiveChart.SetElement (msoElementErrorBarStandardError) will work fine. However, you should call the chart by name, like so:
ThisWorkbook.Worksheets("Sheet1").ChartObjects("Chart 1").Chart.SetElement (msoElementErrorBarStandardError)
I am trying to copy some charts (embedded) in different worksheets of an excel workbook using vbscript into different slides of a powerpoint. I would like to keep the link between the excel sheet and the powerpoint while doing so and therefore I used the below piece of code that allows me to keep formatting and link (instead of a simple paste or PasteSpeical. Is there any other way?) :
For i = 1 to TotalNumWorkSheets 'I iterated with indices.
Set pptSlide = pptPres.Slides.Add(i, 11) 'There is one opening slide before this.
set ws = wb.Worksheets(i)
ws.ChartObjects(1).Chart.ChartArea.Copy
pptApp.CommandBars.ExecuteMso("PasteExcelChartSourceFormatting")
pptApp.CommandBars.ReleaseFocus
With pptSlide
.Shapes.Title.TextFrame.TextRange.Text = objCurSheet.Name
'Adding some more textboxes here. Working fine. Position checks out in PPT.
.Shapes(.Shapes.Count).Left = 20 'Doesn't work for all slides.
End With
Next
The code works and copies all the charts, creates titles, adds new text as expected, but I am not able to position the charts on individual slides because after the ExecuteMso command, I don't know how to access the reference to the chart. I read in one of the SO posts that pasting using this method looses the chart selection but you can access the last .Shapes object since pasting always adds the object to the end of the list. Is that always the case? I tried accessing and positioning my chart by accessing the last object but it only works for the first slide of the loop (i.e. the first chart pasted is shifted to Left=20). The rest all charts in other slides are centered. Can someone explain where and how to add the formatting chart options? I ran into an even weirder problem. If I increase the number of worksheets, even the first plot looses it's Left formatting. The above code is the only place where I add formatting so I don't know what is happening. I am sure I am not formatting it correctly.
Many thanks for your suggestions.
Edit: One additional thing which I tested. I am using
WScript.Sleep 500
code before the For loop ends since it gives enough time for earlier operations to finish (at least that's what I understood from many other google searches).
So after some more searching and testing, I found a solution (for my case at least).
Moved the WScript.Sleep 1000 (500 didn't work for me) statement just below CommandBars.ReleaseFocus.
It makes some sense now since it is the Chart copying, pasting and linking from excel that needs time. Especially with source formatting. After that there is only text generation which I believe is not so heavy.
Cleared all the set Object variables when not used. Especially the ones associated with the "With" keyword.
set obj = CreateObject()
With obj
'Do something here.
End With
set obj = Nothing
Not clearing them, apparently, can also prevent you from closing the applications even after you use the .Close and .Quit method. At least that's what I observed. I found PowerPoint.exe running in the task manager when nothing was opened.
After doing the above, I am able to copy with format the charts and also able to set the position of the charts. The weird problem of larger number of worksheets also disappeared. Hopefully, it might help others. If someone thinks the observations are incorrect or troublesome, please correct.
I have a program that copies the cells and overlaying map. The area that is being copied has color gradient conditionals, lots of data, and overlapping picture objects. using the code:
range.CopyPicture Appearance:=xlScreen, Format:=xlPicture
Using xlPicture has caused the code to not be able to paste and have all sorts of excel errors such as memory and resources limits hit.
range.CopyPicture Appearance:=xlScreen, Format:=xlBitmap
XlBitmap on the other hand removes this error.
I understand having that many entities to copy is taxing. Does the screenshot take into account the object natures within the range of capture? if so is there a way to reduce the load or remove that calculation?
Just to let you all know, I'm a beginner to VBA and I'm using Excel and PowerPoint 2013.
The aim: I'm writing code in Excel VBA to paste a chart from Excel into PowerPoint. Then when it's pasted, move it to a set place within the slide.
The code I used: The framework of the code I started with is in http://peltiertech.com/Excel/XL_PPT.html#chartppt, the part called 'Paste the Active Excel Chart into the Active PowerPoint Slide (Early Binding)'.
The main difference is around the 'Paste' part, this is instead a 'PasteSpecial' and my code is as follows:
.
Charty.CopyPicture
ppApp.ActivePresentation.Slides(SlideNumber).Shapes.PasteSpecial (ppPasteEnhancedMetafile)
' Setting the correct position on the slide
ppApp.ActiveWindow.Selection.ShapeRange.Top = ChartTop
ppApp.ActiveWindow.Selection.ShapeRange.Left = ChartLeft
(Note. ChartTop and ChartLeft have been defined earlier)
The issues: I'm aware that after the PasteSpecial it doesn't have a select statement. However, (1) When I run the above code I get a runtime error '-2147188160' saying the Selection.ShapeRange is an invalid request (in the 'ChartTop' line), ie. it isn't selected so it can't be moved. (2) When I add a select statement to the 'Paste.Special' line I get an 'Object required' error on the new 'PasteSpecial' line, ie. it doesn't recognise it as a paste select statement.
The odd part: When I run the same macro on other people's computers using the exact same Excel and PowerPoint files it works (without the select statement in the 'PasteSpecial' line). I've looked at 'Tools' => 'References', and both of our computer have the same settings.
The questions: Is there a setting that I have overlooked on my computer which prevents the code from working? Is there a way after I've pasted it to reselect it before it is moved (I should tell you that the macro is to paste in many graphs into ppt simultaneously)? How come for other people at my work it works on their computers without the 'select' part of the PasteSpecial statement? How come when I use the Shapes.PasteSpecial (ppPasteEnhancedMetafile).Select statement, it doesn't recognise it as an object?
I hope that's clear.
Thanks in advance.
Dim oSh as Shape
Set oSh = ppApp.ActivePresentation.Slides(SlideNumber).Shapes.PasteSpecial (ppPasteEnhancedMetafile)(1)
Now you don't need to select anything (which is best avoided whenever possible). Just manipulate the pasted shape, oSh, directly.
The curious syntax (the (1) at the end) is because Shapes.Paste or .PasteSpecial returns a shaperange, not a shape; the (1) causes it to assign the first shape in the range to the oSh variable. Since there's only one shape in the range, that suits us just fine.