Pasting multiple linked Excel Charts to Word returning Run-Time Error 5345 Word Cannot Obtain the Data - excel

I am trying to copy multiple Excel charts and paste them to a Word document, on separate pages, as the data type linked OLEObject but I am getting a run-time error.
Run-time error '5343':
Word cannot obtain the data for the
{00020832-0000-0000-C000-000000000046 link.
This is code that I've used in the past but literally, the only thing I changed in this code is to add an outer loop that processes the worksheets in the active workbook. Since adding that outer loop it no longer works, which is a little strange to me because I don't really see what is different.
It works for the first sheet (the currently active one), but fails when the loop moves to the next sheet. It does not matter whether the chart is pasted with or without a link.
Here is the full code for your reference:
Sub ExportingToWord_MultipleCharts()
'Declare Word Variables
Dim WrdApp As Word.Application
Dim WrdDoc As Word.Document
Dim SecCnt As Integer
'Declare Excel Variables
Dim ChrtObj As ChartObject
Dim Rng As Range
'Create a new instance of Word
Set WrdApp = New Word.Application
WrdApp.Visible = True
WrdApp.Activate
'Create a new word document
Set WrdDoc = WrdApp.Documents.Add
'Loop through each worksheet in the active workbook.
For Each WrkSht In ActiveWorkbook.Worksheets
'Loop through the charts on the active sheet
For Each ChrtObj In WrkSht.ChartObjects
'Copy the chart
ChrtObj.Chart.ChartArea.Copy
'Paste the Chart in the Word Document
With WrdApp.Selection
.PasteSpecial Link:=True, DataType:=wdPasteOLEObject, Placement:=wdInLine
End With
'Add a new page to the document.
WrdApp.ActiveDocument.Sections.Add
'Go to the newly created page.
WrdApp.Selection.GoTo What:=wdGoToPage, Which:=wdGoToNext
Next ChrtObj
Next WrkSht
End Sub
It returns the error on the following line:
'Paste the Chart in the Word Document
With WrdApp.Selection
.PasteSpecial Link:=True, DataType:=wdPasteOLEObject, Placement:=wdInLine
End With

I found a workaround, but it still doesn't explain why the error is happening. What I had to do is activate the actual worksheet in the loop.
'***ACTIVATE THE WORKSHEET IN ORDER TO REMOVE THE ERROR***
WrkSht.Activate
For whatever reason, this seemed to remove the error from popping up. However, I find this strange because when I've exported charts from PowerPoint I am not required to activate the worksheet in order to copy it. Here is the code with the adjustments, I've called out the section I added.
Sub ExportingToWord_MultipleCharts()
'Declare Word Variables
Dim WrdApp As Word.Application
Dim WrdDoc As Word.Document
Dim SecCnt As Integer
'Declare Excel Variables
Dim ChrtObj As ChartObject
Dim Rng As Range
'Create a new instance of Word
Set WrdApp = New Word.Application
WrdApp.Visible = True
WrdApp.Activate
'Create a new word document
Set WrdDoc = WrdApp.Documents.Add
'Loop through each worksheet in the active workbook.
For Each WrkSht In ActiveWorkbook.Worksheets
'***ACTIVATE THE WORKSHEET IN ORDER TO REMOVE THE ERROR***
WrkSht.Activate
'Loop through the charts on the active sheet
For Each ChrtObj In WrkSht.ChartObjects
'Copy the chart
ChrtObj.Chart.ChartArea.Copy
'Paste the Chart in the Word Document
With WrdApp.Selection
.PasteSpecial Link:=False, DataType:=wdPasteOLEObject, Placement:=wdInLine
End With
'Add a new page to the document.
WrdApp.ActiveDocument.Sections.Add
'Go to the newly created page.
WrdApp.Selection.GoTo What:=wdGoToPage, Which:=wdGoToNext
Next ChrtObj
Next WrkSht
End Sub

Related

Copy all textboxes (contained in each worksheet) to a word document

I am trying to export each worksheet content (textboxes and shapes, no cellcontent) into a word document. The result is not what I expected. If there are 2 worksheets each one with a text box, 1 text box will be copied twice and the other one won't be copied at all!
Private Sub Export()
Dim WordApp As Word.Application
Set WordApp = CreateObject("Word.Application")
On Error Resume Next
WordApp.Documents.Add
WordApp.Visible = True
For Each ws In ActiveWorkbook.Worksheets
ws.Shapes.SelectAll
Selection.Copy
WordApp.Selection.PasteSpecial DataType:=wdPasteShape
Application.CutCopyMode = False
Next ws
End Sub
What I am missing:
Insert a page break after each ws is exported
Understanding why a textbox from a worksheet is copied twice and another textbox from a different worksheet is not copied at all
1. Adding page breaks
If you want to insert a page break at the end of your Word file, you can (1) select the end of the Word content section and (2) insert the page break like this:
WordApp.Selection.EndKey Unit:=wdStory
WordApp.Selection.InsertBreak
Your code would then look like this:
Private Sub Export_v1()
Dim WordApp As Word.Application
Set WordApp = CreateObject("Word.Application")
On Error Resume Next
WordApp.Documents.Add
WordApp.Visible = True
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
ws.Shapes.SelectAll
Selection.Copy
WordApp.Selection.PasteSpecial DataType:=wdPasteShape
Application.CutCopyMode = False
WordApp.Selection.EndKey Unit:=wdStory
WordApp.Selection.InsertBreak
Next ws
End Sub
2. Avoiding the same text box to be pasted
If you run the above macro, you'll still get the textbox(s) from the first sheet twice. Why? Because you are using Selection.Copy which is dependent on which sheet is active.
To make sure that the correct sheet is active, simply add ws.Activate before selecting the shapes like this:
Private Sub Export_v2()
Dim WordApp As Word.Application
Set WordApp = CreateObject("Word.Application")
On Error Resume Next
WordApp.Documents.Add
WordApp.Visible = True
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
ws.Activate
ws.Shapes.SelectAll
Selection.Copy
WordApp.Selection.PasteSpecial DataType:=wdPasteShape
Application.CutCopyMode = False
WordApp.Selection.EndKey Unit:=wdStory
WordApp.Selection.InsertBreak
Next ws
End Sub
3. Potential improvements
3.1 Avoid using Select inside Excel
Avoiding using Select in Excel VBA can lead to major speed improvements. However, in this case you can't just replace
ws.Shapes.SelectAll
Selection.Copy
with
ws.Shapes.Copy
as it won't copy the shapes. Instead, you would need to loop through each shape in the worksheet to paste them one by one. This might introduce more complications to your code, so if speed is not an issue, you could keep it as this.
3.2 Reset objects to nothing
To avoid Excel running out of memory, it is a good practice to always reset objects to nothing after you are done using them (at the end of your procedure in this case):
Set WordApp = Nothing

Copy Range of Cells to a Word Document based on IDs from a different column

So we have this table we are using at the office. I changed the Column Name and Content for confidentiality purposes.
We're trying create a Word Document for each ID consisting of all the Name's and Surnames for that ID only from our Excel file.
i.e. A new Word Document is created for ID1. The contents are all the Names and Surnames only for that ID1 excluding the Column Name. Another Word Document will be created for the next ID available until all IDs have their own document,
So far this is what I got:
Sub test()
Dim copyRng As Range
Dim lastrow As Long
lastrow = Cells(Rows.Count, "A").End(xlUp).Row
Set copyRng = Range("B2:C" & lastrow)
Range("B2:C" & copyRng.Rows.Count).Select
Selection.Copy
'Declare Word Variables
Dim WrdApp As Word.Application
Dim WrdDoc As Word.Document
'Create a new instance of Word
Set WrdApp = New Word.Application
WrdApp.Visible = True
WrdApp.Activate
'Create a new Document in the Word Application
Set WrdDoc = WrdApp.Documents.Add
WrdDoc.Activate
WrdDoc.Range(WrdDoc.Characters.Count - 1).Paste
End Sub
I can't seem to copy only the rows for a specific ID.
Can anyone suggest a better solution copy only the cells based on the IDs?
I simplified my problem in the meantime.
First I select the cells I want to be copied over to a Word Document.
Then I run this code:
Selection.Copy
'Declare Word Variables
Dim WrdApp As Word.Application
Dim WrdDoc As Word.Document
'Create a new instance of Word
Set WrdApp = New Word.Application
WrdApp.Visible = True
WrdApp.Activate
'Create a new Document in the Word Application
Set WrdDoc = WrdApp.Documents.Add
WrdDoc.Activate
With WrdDoc.Range(WrdDoc.Characters.Count - 1).Characters.Last
.PasteExcelTable False, True False
With .Tables(1)
.AutoFitBehavior wdAutoFitWindow
End With
.InsertAfter Chr(1)
End With
This way, I just have to highlight the cells I want to be copied over to Word and Run the Macro. The Macro will create a new Word Document for me.

Export Excel Chart To Word Using PasteFormat is Returning Error 4605 Command Not Available

So I'm trying to understand what is wrong with my code. All I'm doing is taking some charts in my Excel workbook and exporting them to a Word document but I keep getting an error if I try to paste them a certain way. Here's my code:
Sub ExportingToWord_MultiplePages2()
'Declare Word Variables
Dim WrdApp As Word.Application
Dim WrdDoc As Word.Document
'Declare Excel Variables
Dim ChrtObj As ChartObject
'Create a new instance of Word
Set WrdApp = New Word.Application
WrdApp.Visible = True
'Create a new word document
Set WrdDoc = WrdApp.Documents.Add
'Loop through the charts on the active sheet
For Each ChrtObj In ActiveSheet.ChartObjects
'Copy the chart
ChrtObj.Chart.ChartArea.Copy
**'THIS WON'T RETURN AN ERROR**
With WrdApp.Selection
.PasteAndFormat Type:=wdChartPicture
End With
'**THIS WILL RETURN THE ERROR**
With WrdApp.Selection
.PasteAndFormat Type:=wdChartLinked
End With
'Clear the Clipboard.
Application.CutCopyMode = False
Next ChrtObj
End Sub
This is the weird part because I've provided two different ways to paste, the first one I paste it as a chart picture and that works fine. However, if I try wdChart or wdChartLinked it won't work! I get Error 4605 "Command Not Avaiable".
Any thoughts as to why this would be the case?
So I found a workaround to the problem, but I'm still not sure why PasteFormat will not work with a linked chart.
If I replace:
'**THIS WILL RETURN THE ERROR**
With WrdApp.Selection
.PasteAndFormat Type:=wdChartLinked
End With
With the following, I no longer get an error:
'**THIS WILL NOT RETURN AN ERROR**
With WrdApp.Selection
.PasteSpecial Link:=True, DataType:=wdPasteOLEObject
End With
I guess it has to do something with the format of the chart or something, but I still find it strange that I can paste it as a picture using PasteFormat but not as a linked chart.

I want to paste a copied cell block from Excel into a chart's data in a PPT presentation using VBA

I am writing a macro through Excel that will help me do the steps below. Currently, I am stuck at step 3.
'Copy specific cellblock in Excel sheet
'Open existing Powerpoint presentation (which exists of four slides with approximately 6-7 charts on each slides whose underlying data has to be replaced with the copied cellblock)
'Select specific chart on slide 1
'Open the specific chart's underlying data by right clicking on "Edit Data"
Select the cellblock in the sheet that pops up and replace it with the data that was copied from Excel in step 1
My issue at the moment lies in step 3, where I am not able to select any chart in my PowerPoint. I would also appreciate all guidance that could help me with step 4 and 5 as well.
My current code looks as the following:
Sub MyMacroRätt()
'Marks and copies a cell block in my Excel file
ActiveSheet.Range("R55", "T75").Select
Selection.Copy
'Open an existing PowerPoint file
Dim PPT As PowerPoint.Application
Set PPT = New PowerPoint.Application
PPT.Visible = True
PPT.Presentations.Open Filename:="C:\Users\seleveafe\Desktop\XXXXXX.pptm"
Dim PPPres As PowerPoint.Presentation
Set PPPres = PPT.ActivePresentation
Dim pslide As PowerPoint.Slide
Dim pchart As PowerPoint.Chart
'Mark the first chart on the first slide
With ActiveWindow.Selection.ShapeRange(1)
If .HasChart = True Then
'Open Edit Data-sheet for selected chart
Chart.ActivateChartDataWindow
End If
End With
'Select existing data i Edit Data-sheet and replace with copied data from Excel
End Sub
Thanks Domenic, it actually worked!
Now I want to repeat this again for more charts in my PPT, so in the first step "Set rngCopyFrom = ActiveSheet.Range("R55", "T75") I will change the cell block that should be copied from Excel. However, when I will repeat the whole code you sent I also want to change the selected chart into THE SECOND CHART on the first slide in the PPT. Do you have ideas on how I can adjust this section so that it instead selects the second chart in slide 1, and pastes the new cell block into that charts worksheet?
If pptShape.HasChart Then 'first chart
In other words, I want a code that selects the second chart on slide 1, another code that selects the third chart on slide 1, another code that selects the fourth chart on slide 1..... and so on. In total I have 8 charts on each slide, and in total I have four slides with charts whose data that needs to be updated.
The following macro opens the specified PowerPoint file, activates the ChartData so that its workbook is opened, copies the specified data into the first worksheet of the workbook, starting at A2, and then closes it. You'll need to change the destination cell (A2) accordingly.
Option Explicit
Sub MyMacroRätt()
Dim pptApp As PowerPoint.Application
Dim pptPres As PowerPoint.Presentation
Dim pptShape As PowerPoint.Shape
Dim rngCopyFrom As Range
Set rngCopyFrom = ActiveSheet.Range("R55", "T75")
Set pptApp = New PowerPoint.Application
pptApp.Visible = True
Set pptPres = pptApp.Presentations.Open(Filename:="C:\Users\seleveafe\Desktop\XXXXXX.pptm")
With pptPres.Slides(1) 'first slide
For Each pptShape In .Shapes
If pptShape.HasChart Then 'first chart
Exit For
End If
Next pptShape
If Not pptShape Is Nothing Then
pptShape.Chart.ChartData.Activate
With rngCopyFrom
pptShape.Chart.ChartData.Workbook.Worksheets(1).Range("a2") _
.Resize(.Rows.Count, .Columns.Count).Value = .Value
End With
pptShape.Chart.ChartData.Workbook.Close
End If
End With
Set pptApp = Nothing
Set pptPres = Nothing
Set pptShape = Nothing
Set rngCopyFrom = Nothing
End Sub
Edit
To choose which chart to update, for example the second chart, try the following instead...
Option Explicit
Sub MyMacroRätt()
Dim pptApp As PowerPoint.Application
Dim pptPres As PowerPoint.Presentation
Dim pptShape As PowerPoint.Shape
Dim rngCopyFrom As Range
Dim ChartNum As Long
Dim ChartIndex As Long
ChartNum = 2 'second chart
Set rngCopyFrom = ActiveSheet.Range("R55", "T75")
Set pptApp = New PowerPoint.Application
pptApp.Visible = True
Set pptPres = pptApp.Presentations.Open(Filename:="C:\Users\seleveafe\Desktop\XXXXXX.pptm")
With pptPres.Slides(1) 'first slide
ChartIndex = 0
For Each pptShape In .Shapes
If pptShape.HasChart Then
ChartIndex = ChartIndex + 1
If ChartIndex = ChartNum Then
Exit For
End If
End If
Next pptShape
If Not pptShape Is Nothing Then
pptShape.Chart.ChartData.Activate
With rngCopyFrom
pptShape.Chart.ChartData.Workbook.Worksheets(1).Range("a2") _
.Resize(.Rows.Count, .Columns.Count).Value = .Value
End With
pptShape.Chart.ChartData.Workbook.Close
End If
End With
Set pptApp = Nothing
Set pptPres = Nothing
Set pptShape = Nothing
Set rngCopyFrom = Nothing
End Sub

How to dynamically reference PowerPoint slides using VBA

I've written/compiled a macro that opens an Excel file, creates a PowerPoint chart and populates the chart worksheet with data from a worksheet in the Excel file.
I'm trying to alter the macro to loop through the Excel file's worksheets and:
for each worksheet create a PowerPoint slide and chart
populate the PowerPoint chart with data from the worksheet in the Excel file
Presently when I run the macro, the first PowerPoint chart and slide is created correctly. The second slide is created for the Excel file's second worksheet but the PowerPoint chart is not created correctly. The workbook that I'm testing the macro on has two worksheets.
What is the correct way to dynamically reference each new PowerPoint slide? As of now I've been using:
Set pptWorkSheet = pptWorkBook.Worksheets(ActivePresentation.Slides.Count) 'sorta works-changed 8/19
When I go to the debugger it says ActivePresentation.Slides.Count = 2 so I am not sure as to why its not transferring the data to the second PowerPoint chart.
I also may not be referring to the Excel file worksheets correctly here:
pptWorkSheet.Range("a2:b5").Value = xlWB.ActiveSheet.Range("a2:b5").Value
Below is the full macro:
Sub CreateChartAllWKs()
'Create variables
Dim myChart As Chart
Dim pptChartData As ChartData
Dim pptWorkBook As Excel.Workbook
Dim pptWorkSheet As Excel.Worksheet
Dim xlApp As Excel.Application
Dim xlWB As Workbook
Dim xlWS As Worksheet
' Create new excel instance and open relevant workbook
Set xlApp = New Excel.Application
xlApp.Visible = True 'Make Excel visable
Set xlWB = xlApp.Workbooks.Open("C:\filepath\ExcelData.xlsm", True, False) 'Open relevant workbook
'Loop through each worksheet in xlWB and transfer data to new pptWorkBook and
'create new PowerPoint chart
For Each xlWS In ActiveWorkbook.Worksheets
'Add a new slide where we will create the PowerPoint worksheet and chart
ActivePresentation.Slides.Add ActivePresentation.Slides.Count + 1, ppLayoutText
ActiveWindow.View.GotoSlide ActivePresentation.Slides.Count
Set activeSlide = ActivePresentation.Slides(ActivePresentation.Slides.Count)
' Create the chart and set a reference to the chart data.
Set myChart = activeSlide.Shapes.AddChart.Chart 'changed 8/19
Set pptChartData = myChart.ChartData
' Set the PowerPoint Workbook and Worksheet references.
Set pptWorkBook = pptChartData.Workbook
Set pptWorkSheet = pptWorkBook.Worksheets(ActivePresentation.Slides.Count) 'sorta works-changed 8/19
' Add the data to the PowerPoint workbook.
pptWorkSheet.ListObjects("Table1").Resize pptWorkSheet.Range("A1:B5")
pptWorkSheet.Range("Table1[[#Headers],[Series 1]]").Value = "Items"
pptWorkSheet.Range("a2:b5").Value = xlWB.ActiveSheet.Range("a2:b5").Value 'transfer data from ExcelWB to pptWorkSheet (i.e. the PowerPoint workbook)
' Apply styles to the chart.
With myChart
.ChartStyle = 4
.ApplyLayout 4
.ClearToMatchStyle
End With
' Add the axis title.
With myChart.Axes(xlValue)
.HasTitle = True
.AxisTitle.Text = "Units"
End With
'Apply data labels
myChart.ApplyDataLabels
Next xlWS
' Clean up the references.
Set pptWorkSheet = Nothing
' pptWorkBook.Application.Quit
Set pptWorkBook = Nothing
Set pptChartData = Nothing
Set myChart = Nothing
'Clean up Excel references.
Set xlApp = Nothing
'Option to close excel workbook
'ExcelWB.Close
End Sub
I think the problem you are running into is how PowerPoint and Excel store slide numbers and worksheet numbers. PowerPoint at least 3 different attributes with Slides, including "Slide IDs", "Slide Indexes" and "Slide Numbers". They are all different and make things a pain when you are trying to reference them. What I like to do is actually set the reference of the slide right when I am creating the slide:
Set CurSlide = ActivePresentation.Slides.Add(ActivePresentation.Slides.Count + 1, ppLayoutText)
This way right when you create the slide you now have a reference to it.
Additionally I find that using a number as a worksheet reference can also cause issues since if you reference the 5th worksheet it may not be the 5th worksheet at all. You have to look in the VBA editor of Excel to see what sheet gets what reference. However if you are able to refer to the worksheet name such as "Sheet1", "Sheet2", "OtherWorksheet" etc. You can make things a lot easier. To put this a little more in perspective if you make a sheet named "5" and then call the worksheet with.
Set ws = ActiveWorkBook.WorkSheets(5)
It will not work. You would need to use
Set ws = ActiveWorkBook.Worksheets("5")
Hopefully that makes sense. This part is not necessary but it makes debugging a lot easier if you do run into issues. The way I would recommend to do this is not in my code below because I don't have your workbook.
Set PPtWorkSheet = pptWorkBook.Worksheets("Sheet" & CurSlide.SlideIndex)
I re-wrote a few lines of your code and I was able to get it to work. However I do not have a copy of your workbook so I am not 100% sure this would work. Consider changing the worksheet names on your workbook if you still have trouble referencing the worksheet from the slide Index.
The revised code is below let me know if you have any questions.
Sub CreateChartAllWKs()
'Create variables
Dim myChart As Chart
Dim pptChartData As ChartData
Dim pptWorkBook As Excel.Workbook
Dim pptWorkSheet As Excel.Worksheet
Dim xlApp As Excel.Application
Dim xlWB As Excel.Workbook
Dim xlWS As Excel.Worksheet
Dim CurSlide As Slide 'new from update
' Create new excel instance and open relevant workbook
Set xlApp = New Excel.Application
xlApp.Visible = True 'Make Excel visable
Set xlWB = xlApp.Workbooks.Open("C:\filepath\ExcelData.xlsm", True, False) 'Open relevant workbook
'Loop through each worksheet in xlWB and transfer data to new pptWorkBook and
'create new PowerPoint chart
For Each xlWS In ActiveWorkbook.Worksheets
'Add a new slide where we will create the PowerPoint worksheet and chart
'Set CurSlide = ActivePresentation.Slides.Add ActivePresentation.Slides.Count + 1, ppLayoutText
ActiveWindow.View.GotoSlide ActivePresentation.Slides.Count
'This is my recommendation
Set CurSlide = ActivePresentation.Slides.Add(ActivePresentation.Slides.Count + 1, ppLayoutText)
' Create the chart and set a reference to the chart data.
Set myChart = CurSlide.Shapes.AddChart.Chart 'changed 8/19
Set pptChartData = myChart.ChartData
' Set the PowerPoint Workbook and Worksheet references.
Set pptWorkBook = pptChartData.Workbook
Set pptWorkSheet = pptWorkBook.Worksheets(CurSlide.SlideIndex) 'From Update
' Add the data to the PowerPoint workbook.
pptWorkSheet.ListObjects("Table1").Resize pptWorkSheet.Range("A1:B5")
pptWorkSheet.Range("Table1[[#Headers],[Series 1]]").Value = "Items"
pptWorkSheet.Range("a2:b5").Value = xlWB.ActiveSheet.Range("a2:b5").Value 'transfer data from ExcelWB to pptWorkSheet (i.e. the PowerPoint workbook)
' Apply styles to the chart.
With myChart
.ChartStyle = 4
.ApplyLayout 4
.ClearToMatchStyle
End With
' Add the axis title.
With myChart.Axes(xlValue)
.HasTitle = True
.AxisTitle.Text = "Units"
End With
'Apply data labels
myChart.ApplyDataLabels
Next xlWS
' Clean up the references.
Set pptWorkSheet = Nothing
' pptWorkBook.Application.Quit
Set pptWorkBook = Nothing
Set pptChartData = Nothing
Set myChart = Nothing
'Clean up Excel references.
Set xlApp = Nothing
'Option to close excel workbook
'ExcelWB.Close
End Sub

Resources