I have this challenge to create a macro to extract data from ppt.
I need to extract the data from tables in a ppt and paste them into Excel.
I can extract data and paste it into Excel, but the tables are printing one below the other, like this:
I want the tables to to printed like this:
The below image is from ppt how the tables are placed in ppt,
in similar way the tables need to be printed in the Excel spreadsheet:
I tried this:
Sub ExportToExcelSheet()
'Declare PPT variables
Dim pptPres As Presentation
Dim pptSlide As Slide
Dim pptShape As Shape
Dim pptPlaceholder As PlaceholderFormat
Dim pptTable As Table
'Declare Excel variables
Dim xlApp As Excel. Application
Dim xlBook As Excel. Workbook
Dim xlSheet As Excel. Worksheet
Dim xlRange As Excel.Range
'Access the active presentation
Set pptPres = Application.ActivePresentation
On Error Resume Next
Set xlApp = GetObject(, "EXCEL.Application")
If Err.Number = 429 Then
Err.Clear
Set xlApp = New Excel.Application
xlApp.Visible = True
Set xlBook = xlApp.Workbooks.Add
Set xlSheet = xlBook.Worksheets.Add
End If
Set xlBook = xlApp.Workbooks("Extract.xlsx")
Set xlSheet = xlBook.Worksheets("Sheet1")
For Each pptSlide In pptPres.Slides
For Each pptShape In pptSlide.Shapes
If pptShape.Type = msoTable Then
Set pptTable = pptShape.Table
pptShape.Copy
Set xlRange = xlSheet.Range("A100").End(xlUp)
If xlRange.Address <> "$A$1" Then
Set xlRange = xlRange.Offset(3, 0)
End If
xlSheet.Paste Destination:=xlRange
End If
Next
Next
xlSheet.Columns.Range("A1").ColumnWidth = 5
xlSheet.Columns.Range("B1").ColumnWidth = 25
xlSheet.Rows.RowHeight = 20
End Sub
Because xlRange is defined by searching the last used cell in Column A, you are only pasting to Column A and thus, your current output is one after the other down this column.
You can keep it this way and then reposition each table after they are in Excel by serching each title for "Sub*" and if found put it on row (say) 10 otherwise using a similar method to your last row, find the last column and offset it say, 3 columns to the right.
Something like this AFTER your existing for loop...
Dim RowCounter As Long
Dim BottomRowOfTable As Long
Dim LastColumn As Long
Dim MyArray As Variant
For RowCounter = 1 To xlRange 'You can reuse this as the last destination which would be the last header row in the list you pasted.
With xlSheet
If .Cells(RowCounter, 1).Value Like "Sub*" Then
BottomRowOfTable = .Cells(RowCounter, 1).End(xlDown).Row
LastColumn = .Cells(8, .Columns.Count).End(xlToLeft).Column
MyArray = .Range(.Cells(RowCounter, 1), .Cells(BottomRowOfTable, 1)).Value
.Range(.Cells(8, LastColumn + 2).Address).Resize(UBound(MyArray)).Value = MyArray
.Range(.Cells(RowCounter, 1), .Cells(BottomRowOfTable, 1)).Clear
ElseIf .Cells(RowCounter, 1).Value Like "Station*" Then
BottomRowOfTable = .Cells(RowCounter, 1).End(xlDown).Row
LastColumn = .Cells(1, .Columns.Count).End(xlToLeft).Column
MyArray = .Range(.Cells(RowCounter, 1), .Cells(BottomRowOfTable, 1)).Value
.Range(.Cells(1, LastColumn + 2).Address).Resize(UBound(MyArray)).Value = MyArray
.Range(.Cells(RowCounter, 1), .Cells(BottomRowOfTable, 1)).Clear
End If
End With
Next RowCounter
You will probably need to change some of the cell references so it targets the right cell to find the title and/or move each table to the correct location.
I also did not test with formatting per your current output to Excel.
I think there is probably a cleaner way to do this but this method can achieve your goal.
Related
I have an excel sheet that has the data, I have a powerpoint presentation that has a few charts. I need to run a report eveyday, so i am trying to automate it. I wrote a vba script to copy and paste the data from excel sheet to the chart in powerpoint . But i am unable to change the selection region(the data that is displayed on the graph eventhough there may be more data).
I have written the following script. Any help that helps me change the data to be displayed on the chart is appreciated.
Private Sub CommandButton1_Click()
Dim r As Range
Dim powerpointapp As Object
Dim mypresentation As Object
Dim myslide As Object
Dim myshape As Object
Dim ppath As String
Dim titlesh As Object
Dim tdate As String
Dim chartsh As Object
tdate = Format(Date, "mmmm dd, yyyy")
ppath = "path to ppt"
Set powerpointapp = CreateObject(class:="PowerPoint.Application")
Set mypresentation = powerpointapp.Presentations.Open(ppath)
Set myslide = mypresentation.Slides(1)
Set titlesh = myslide.Shapes("Dateh")
titlesh.TextFrame.TextRange.Text = tdate
Set myslide = mypresentation.Slides(2)
Set chartsh = myslide.Shapes("Chart 6")
chartsh.Chart.ChartData.Workbook.Sheets(1).Cells.Clear
Set r = ThisWorkbook.Worksheets("Weekly Tracking").Range("B84:C158")
r.Copy
chartsh.Chart.ChartData.Workbook.Sheets(1).Range("A2:B74").Value = r.Value
powerpointapp.Visible = True
powerpointapp.Activate
Application.CutCopyMode = False
End Sub
Depends on what your data looks like. You may use .end or usedrange or a loop to looking for keyword in order to locate the end of data.
Some code just to demo the idea:
Dim lastline1 As Long, lastline2 As Long
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Weekly Tracking")
lastline1 = ws.Cells(84, 2).End(xlDown).Row() 'Need to check whether row 84 is the last row, otherwise it may fly to 65536 or 1048576.
lastline2 = ws.UsedRange(ws.UsedRange.Rows.Count, ws.UsedRange.Columns.Count).Row
Set r = ThisWorkbook.Worksheets("Weekly Tracking").Range("B84:C" & lastline2)
I currently have a larger table in excel that I am trying to copy/paste into an existing PPT doc. Since the table is too long to fit on one slide I'm trying to have it take every 15 rows and paste on a new slide. The code below works, but it is set up to take a specified range for each slide. I've tried several other ways, but they all end up opening the PPT doc and essentially doing nothing.
Sub ExcelToPowerPoint()
Dim PPapp As PowerPoint.Application
Dim PPpres As PowerPoint.Presentation
Dim PPslide As PowerPoint.Slide
Dim Xlws As Worksheet
Dim rng As Range
Dim myPresentation As Object
Dim mySlide As Object
Dim PowerPointApp As Object
Dim MySlideArray As Variant
Dim MyRangeArray As Variant
Dim x As Long
Dim shp As Object
Dim i As Long
Dim j As Integer
Set Xlws = ActiveSheet
Set PPapp = New PowerPoint.Application
Set PPpres = PPapp.Presentations.Open("insert name of doc here")
PPapp.ActivePresentation.Slides(4).Select
PPapp.Activate
PPapp.Visible = True
'List of PPT Slides to Paste to
MySlideArray = Array(4, 5, 6)
'List of Excel Ranges to Copy from
MyRangeArray = Array(Sheets("Template").Range("B1:K16"), Sheets("Template").Range("B16:K31"), Sheets("Template").Range("B31:K45"))
'Loop through Array data
For x = LBound(MySlideArray) To UBound(MySlideArray)
'Copy Excel Range
MyRangeArray(x).Copy
On Error Resume Next
Set shp = PPpres.Slides(MySlideArray(x)).Shapes.PasteSpecial(ppPasteEnhancedMetafile)
shp.Shapes.PasteSpecial ppPasteEnhancedMetafile
Set mySlide = PPapp.ActiveWindow.Selection.ShapeRange
mySlide.Left = 30
mySlide.Top = 85
mySlide.Height = 150
mySlide.Width = 900
Next x
End Sub
I think this is what you want.
Option Explicit
Sub Test()
Dim lastrow As Long
Dim row1 As Long
Dim row2 As Long
Dim dataRange As Range
With Sheets("Template")
' Get last row on sheet
lastrow = .Cells.Find("*", SearchOrder:=xlByRows, searchdirection:=xlPrevious).row
' Copy data 15 rows at a time
row1 = 1
Do While row1 < lastrow
row2 = row1 + 14
If row2 > lastrow Then
row2 = lastrow
End If
' Copy data range
.Range("B" & row1 & ":K" & row2).Copy
'*********************************
'* Paste data to PowerPoint here *
'*********************************
row1 = row2 + 1
Loop
End With
End Sub
P.S. You might want to read this How to avoid using Select in Excel VBA
I have got this error massage during merging the content of several excel files into one. I know this occurs because there is not much space left.
Can anyone help me how to include a rule like if the space is not enough then open a new worksheet and paste the remaining content there?
This is it:
Sub simpleXlsMerger()
Dim bookList As Workbook
Dim mergeObj As Object, dirObj As Object, filesObj As Object, everyObj As Object
Application.ScreenUpdating = False
Set mergeObj = CreateObject("Scripting.FileSystemObject")
Set dirObj = mergeObj.Getfolder("C:\Users\JudakV\Desktop\xxxmacro\")
Set filesObj = dirObj.Files
For Each everyObj In filesObj
Set bookList = Workbooks.Open(everyObj)
Range("A2:IV" & Range("1000000").End(xlUp).Row).Copy
ThisWorkbook.Worksheets(1).Activate
Range("A1000000").End(xlUp).Offset(1, 0).PasteSpecial Paste:=xlPasteValues
Application.CutCopyMode = False
bookList.Close
Next
End Sub
There is a report of mine which requires to copy and paste the content of several (about 20) excel files into one single file, and if it has more than 1M rows (usually more than that) then open a new worksheet and copy the remaining part there.
I am not good at macros, but it could spare lots of time for me if it would work. But I am troubling with the page limit and to open a new worksheet part kind of stuff...
This code will copy the data to new sheets. I haven't tested on massive amounts of data, but should work.
Public Sub XLMerger()
Dim oFSO As Object
Dim oDir As Object
Dim oFiles As Object
Dim oFle As Object
Dim wrkBk As Workbook
Dim tgtLastCell As Range 'Target last cell.
Dim srcLastCell As Range 'Source last cell.
Dim lRequiredRows As Long
Dim lAvailableRows As Long
Dim tgtSheet As Worksheet
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oDir = oFSO.GetFolder(""C:\Users\JudakV\Desktop\xxxmacro\"")
Set oFiles = oDir.Files
'Will be pasting data into this sheet.
Set tgtSheet = ThisWorkbook.Worksheets("Sheet1")
For Each oFle In oFiles
If InStr(oFle.Type, "Excel") > 0 Then
Set wrkBk = Workbooks.Open(Filename:=oFle, ReadOnly:=True)
'Set reference to last cell on Target sheet.
With tgtSheet
'If there is data on the very last row an
'incorrect reference will be returned.
If .Cells(.Rows.Count, 1) <> "" Then
Set tgtLastCell = .Cells(.Rows.Count, 1)
Else
Set tgtLastCell = .Cells(.Rows.Count, 1).End(xlUp)
End If
End With
With wrkBk.Worksheets("Sheet1")
'Set reference to last cell on Source sheet.
Set srcLastCell = .Cells(.Rows.Count, 1).End(xlUp)
'Will it fit?
lRequiredRows = srcLastCell.Row - 1
lAvailableRows = ThisWorkbook.Worksheets("Sheet1").Rows.Count - tgtLastCell.Row
If lRequiredRows <= lAvailableRows Then
'Straight Copy/Paste as it all fits.
.Range(.Cells(2, 1), .Cells(srcLastCell.Row, 256)).Copy
tgtLastCell.Offset(1).PasteSpecial xlPasteValues
Else
'Copy what we can onto old sheet providing there's at least 1 blank row.
If lAvailableRows > 0 Then
.Range(.Cells(2, 1), .Cells(lAvailableRows + 1, 256)).Copy
tgtLastCell.Offset(1).PasteSpecial xlPasteValues
End If
'Create a new sheet, copy headings over and paste remaining data.
'The IIF command ensures lAvailable rows isn't looking at row 0.
Set tgtSheet = ThisWorkbook.Worksheets.Add
ThisWorkbook.Worksheets("Sheet1").Rows(1).Copy Destination:=tgtSheet.Range("A1")
.Range(.Cells(lAvailableRows + IIf(lAvailableRows = 0, 2, 0), 1), .Cells(srcLastCell.Row, 256)).Copy
tgtSheet.Range("A2").PasteSpecial xlPasteValues
End If
End With
Application.DisplayAlerts = False
wrkBk.Close SaveChanges:=False
Application.DisplayAlerts = True
End If
Next oFle
End Sub
I have several Powerpoint files being generated everymonth, these files have several charts with embedded excel tables behind them, for some month some series(columns) are full of zeros, I would like to find a Powerpoint Macro that goes into each chart looks on the embedded excel and deletes columns that are all zeros.
Now I have the code to do it in excel
Sub DeleteColumns()
Dim LR As Long, LC As Long
Dim i As Long, j As Long
LR = Cells.Find(What:="*", SearchDirection:=xlPrevious,SearchOrder:=xlByRows).Row
LC = 52
For j = LC To 1 Step -1
For i = LR To 1 Step -1
If Cells(i, j).Value = 0 Then
Columns(j).Delete
Exit For
End If
Next i
Next j
End Sub
And its working, I just dont know how to reference all the charts inside the powerpoint and then target the embedded excel tables behing them.
Many Thanks
You can expose all the underlying excel chart like so.
I'm not sure of how you are looking to remove the zero columns so suggest you add this in at the spot highlighted below.
Sub ChangeChartData()
Dim pptChart As Chart
Dim pptChartData As ChartData
Dim xlWorkbook As Object
Dim sld As Slide
Dim shp As Shape
For Each sld In ActivePresentation.Slides
For Each shp In sld.Shapes
If shp.HasChart Then
Set pptChart = shp.Chart
Set pptChartData = pptChart.ChartData
pptChartData.Activate
Set pptWorkbook = pptChartData.Workbook
'your delete code here
pptWorkbook.Close True
End If
Next
Next
Set pptWorkbook = Nothing
Set pptChartData = Nothing
Set pptChart = Nothing
End Sub
I want to build a macro that connects our Excel-Data-Sheet with our Reporting-Powerpoint-Presentation.
So I have this named Range ("A") selected and copied.
Then I want to paste the data into a shape in Powerpoint which has the same name as my Range ("A").
Sub SyncWithPPT()
Dim pptApp As PowerPoint.Application
Dim pptPres As PowerPoint.Presentation
Dim pptShape As PowerPoint.Shape
Set pptApp = New PowerPoint.Application
pptApp.Visible = msoTrue
Set pptPres = pptApp.presentations.Open("workingPath")
ActiveWorkbook.Names("A").RefersToRange.Select
Selection.Copy
Set pptShape = pptPres.Slides("anySlide").Shapes("A")
pptShape.Table.cell(1, 1).Shape.TextFrame.TextRange.Paste 'Here it won't paste correctly
End Sub
Everything works just fine, except the pasting. When I paste the selection everything is pasted into cell(1, 1).But I want to copy each cell into a different cell. Like it does when you paste with STRG + V.
Any help would be really appreciated.
This worked for me (Office 2007)...
Sub Tester()
Dim ppt, sld
'presentation is already open...
Set ppt = GetObject(, "powerpoint.application")
Set sld = ppt.activepresentation.slides(1)
ActiveSheet.Range("A1:B2").Copy
sld.Shapes(1).Table.Cell(1, 1).Select
ppt.ActiveWindow.View.Paste
Set sld = Nothing
Set ppt = Nothing
End Sub
'this is how to extract each cell information
'assuming that ppt communication is already done.
Dim n As Integer, j As Integer
Dim ultimaFila As Long
j = 1 'columna
ultimaFila = Range("A65536").End(xlUp).Row
For n = 1 To ultimaFila
pptShape.Table.cell(n, j).Value = Application.Workbooks("Book1").Worksheets("Sheet1").Cells(n, j).Value
Next n
End Sub