Loop through excel tables and create graphs - vba

I have multiple tables in one worksheet and I need to loop through tables(list objects) and generate corresponding line graphs. I tried using for each loop and it is not working:
How can I use 'for each' loop to generate graphs? How to reference each list object as a range to my graphs?
Sub chart_create()
Dim tbl As listobject
'Loop through each sheet and table in the workbook
For Each tbl In ActiveSheet.ListObjects
Call graph
End Sub
Next tbl
End Sub
'macro to generate charts
Sub graph()
Dim rng As Range
Dim cht As ChartObject
'how do i change this to reference corresponding list object
Set rng = Selection
Set cht = ActiveSheet.ChartObjects.Add( _
Left:=ActiveCell.Left, _
Width:=450, _
Top:=ActiveCell.Top, _
Height:=250)
'Give chart some data
cht.Chart.SetSourceData Source:=rng
'Determine the chart type
cht.Chart.ChartType = xlLine
End Sub

Pass the Range for the ListObject into your second subroutine as a parameter:
Sub chart_create()
Dim tbl As listobject
'Loop through each sheet and table in the workbook
For Each tbl In ActiveSheet.ListObjects
Call graph tbl.Range
Next tbl
End Sub
'macro to generate charts
Sub graph(rng as range)
Dim cht As ChartObject
Set cht = ActiveSheet.ChartObjects.Add( _
Left:=ActiveCell.Left, _
Width:=450, _
Top:=ActiveCell.Top, _
Height:=250)
'Give chart some data
cht.Chart.SetSourceData Source:=rng
'Determine the chart type
cht.Chart.ChartType = xlLine
End Sub

First, it looks like you have an extra End Sub in there. Next tbl must come before End Sub or else it will never be reached.
Second, you need to pass a reference to your table into the graphing function.
Sub chart_create()
Dim tbl As listobject
'Loop through each sheet and table in the workbook
For Each tbl In ActiveSheet.ListObjects
Call graph(tbl)
Next tbl
End Sub
And then...
Sub graph(tbl As ListObject)
'Make your graph here, referencing the tbl you passed in
End Sub
Edit: Lastly, just to be clear, your comment says that you're "looping through each sheet and table in the workbook," but you're actually just looping through listobjects on the active worksheet. If you want to loop through each worksheet, you'll need to have an extra loop outside the existing loop like:
For Each ws In Worksheets
'For Each tbl In ws.ListObjects....
Next ws

Related

VBA on data source update I want to update a different sheets sort order

I have this working thus far for the datasource sheet. But on another sheet called WatchList I want to update the sort order for 1 of the columns which does a look up when the data source updates. I tried several items and cant get it working.
As far as my range it starts at at the top of the sheet WatchList and goes to column L. And the sort I want to do is on column H.
Private Sub Worksheet_Activate()
Application.EnableEvents = True
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
Dim Sheet As Worksheet, Pivot As PivotTable
For Each Sheet In ThisWorkbook.Worksheets
For Each Pivot In Sheet.PivotTables
Pivot.RefreshTable
Pivot.Update
Next
Next
Dim wb As Workbook
Set wb = ActiveWorkbook
Dim ws As Worksheet
Set ws = wb.Sheets("WatchList")
Dim rng As Range
Set rng = Sheet2.Range("A2:L69")
ws.Range(rng).Sort Key1:=Range("H2:H69"), Order1:=xlAscending, Header:=xlNo
End Sub
I am getting run-time error '1004';
Method 'Range' of object'_Worksheet' failed
Any help is much appreciated

Private Sub User-Defined Type Not Defined Range Sheet

First post. I have the relatively simple code below and am getting a
User-defined type not defined
error. I know that the stand alone code works when I place it into one Sub but for various reasons I want to split it out so that in my larger workbook I can just call on the second sub rather than having to copy and paste the whole loop multiple times. The purpose of the code is to autosize the specified range in excel.
Sub letsGo()
Dim rng As Range
Dim sht As Worksheet
Set rng = ThisWorkbook.Sheets("Sheet1").Range("Range1")
Set sht = ThisWorkbook.Sheets("Sheet1")
Call whyDoesntThisWork(sht, rng)
End Sub
Private Sub whyDoesntThisWork(rangeSheet As Sheet, rangeTable As Range)
Dim Col As Range
Dim reSize As Range
For Each Col In rangeTable.Columns
If Col.Hidden = False Then
Set reSize = rangeSheet.Range(rangeSheet.Cells(rangeTable.Row, Col.Column), rangeSheet.Cells(rangeTable.Rows.Count, Col.Column)) reSize.Columns.autoFit
End If
Next Col
End Sub
You have two different data types:
Private Sub whyDoesntThisWork(rangeSheet As Sheet, rangeTable As Range)
rangeSheet is a Sheet, but when you call it, you pass:
Call whyDoesntThisWork(sht, rng)
sht is of type WorkSheet
That's your inconsistency. I recommend you change your definition to:
Private Sub whyDoesntThisWork(rangeSheet As WorkSheet, rangeTable As Range)
Change rangeSheet As Sheet to rangeSheet As Worksheet

Add and remove rows for bar chart created by VBA

I need to create Bar chart in Excel VBA. I used the code below, but when I am ADDING or DELETING A ROW it is not working.
I need that chart on fixed range (K1). Because when I am calculating for the second time it creates another chart.
How can I change the code to prevent a new chart being added when I adjust the data source?
Private Sub CommandButton2_Click()
Sheets("Sheet7").Range("F2:H12").Select
ActiveSheet.Shapes.AddChart.Select
ActiveChart.ChartType = xlBarClustered
ActiveChart.SetSourceData Source:=Range("Sheet7!$F$2:$H$12")
ActiveChart.SeriesCollection(1).Name = "=Sheet7!$G$1"
ActiveChart.SeriesCollection(2).Name = "=Sheet7!$H$1"
End Sub
In the sample code below it checks to see if a chart called TheChart already exists, and if not, creates a new one. You can now add and remove rows and the chart should will update. Additionally, if you add a new row at the bottom and click the button it will redraw TheChart without creating a new one.
The chart is always located at the top-left of K1 per the rngChartTopLeft variable - which you can adjust if required.
The code assumes that it is running in a Sheet module (hence Set ws = Me) and if you were running it in a standard module you can set the sheet with Set ws = ThisWorkbook.Worksheets("your_sheet").
Option Explicit
Private Sub CommandButton1_Click()
Dim ws As Worksheet
Dim chto As ChartObject
Dim rngChartTopLeft As Range
Dim rngData As Range
' assumes the code is in a sheet object
Set ws = Me
' top left of chart
Set rngChartTopLeft = ws.Range("K1")
' create chart or get existing chart
If ws.ChartObjects.Count = 0 Then
Set chto = ws.ChartObjects.Add( _
Left:=rngChartTopLeft.Left, _
Width:=500, _
Top:=rngChartTopLeft.Top, _
Height:=500)
chto.Name = "TheChart"
Else
Set chto = ws.ChartObjects("TheChart")
End If
' set chart type
chto.Chart.ChartType = xlBarClustered
' get data range per last row of data
Set rngData = ws.Range("F2:G" & ws.Cells(ws.Rows.Count, "G").End(xlUp).Row)
' set new chart range
chto.Chart.SetSourceData rngData
End Sub
please check the below code:
Option Explicit
Private Sub CommandButton1_Click()
Dim mychart As Shape
Dim lastrow As Long
lastrow = Sheet7.Cells(Rows.Count, "F").End(xlUp).Row
For Each mychart In ActiveSheet.Shapes
If mychart.Name = "CommandButton1" Then GoTo exit_
mychart.Delete
exit_:
Next
Sheets("Sheet7").Range("F2:H" & lastrow).Select
ActiveSheet.Shapes.AddChart.Select
ActiveChart.ChartType = xlBarClustered
ActiveChart.SetSourceData Source:=Range("Sheet7!$F$2:$H$" & lastrow)
ActiveChart.SeriesCollection(1).Name = "=Sheet7!$G$1"
ActiveChart.SeriesCollection(2).Name = "=Sheet7!$H$1"
End Sub

Loop through worksheets while exporting range as image

I have the following VBA code that works to export a range of cells into a jpeg into a specified folder. I would like to have it loop through all worksheets in one workbook.
I need help looping this code through all open workbooks. I believe I will need to:
Dim WS As Worksheet, then set up an If statement, insert the below code, end the if statement, then at the end put a Next WS for it to actually loop through. My problem is, is that I keep getting a 91 error when I try to combine my if statement, For Each WS In ThisWorkbook.Sheets If Not WS.Name = "Sheet2" Then, with my code below.
The following code works in one worksheet at a time.
Sub ExportAsImage()
Dim objPic As Shape
Dim objChart As Chart
Dim i As Integer
Dim intCount As Integer
'copy the range as an image
Call ActiveSheet.Range("A1:F2").CopyPicture(xlScreen, xlPicture)
'remove all previous shapes in the ActiveSheet
intCount = ActiveSheet.Shapes.Count
For i = 1 To intCount
ActiveSheet.Shapes.Item(1).Delete
Next i
'create an empty chart in the ActiveSheet
ActiveSheet.Shapes.AddChart
'select the shape in the ActiveSheet
ActiveSheet.Shapes.Item(1).Select
ActiveSheet.Shapes.Item(1).Width = Range("A1:F2").Width
ActiveSheet.Shapes.Item(1).Height = Range("A1:F2").Height
Set objChart = ActiveChart
'clear the chart
objChart.ChartArea.ClearContents
'paste the range into the chart
objChart.Paste
'save the chart as a JPEG
objChart.Export ("C:\Users\------\Desktop\Test\" & Range("B2").Value & ".jpg")
'remove all shapes in the ActiveSheet
intCount = ActiveSheet.Shapes.Count
For i = 1 To intCount
ActiveSheet.Shapes.Item(1).Delete
Next i
End Sub
Add this to your module:
Sub MAIN()
Dim sh As Worksheet
For Each sh In Sheets
sh.Activate
Call ExportAsImage
Next sh
End Sub
and run it. (there is no need to modify your code)

Copy sheet without creating new instances of named ranges?

I'm using the following code to copy a sheet. I also have a few named ranges that are scoped to the Workbook. The problem is, when I do the copy, it creates duplicates of all the named ranges with a scope of the new sheet. Everything works of course but I could potentially have 20+ sheets. I don't need 80 named ranges that are mostly duplicates. How can I avoid this?
Sub btnCopyTemplate()
Dim template As Worksheet
Dim newSheet As Worksheet
Set template = ActiveWorkbook.Sheets("Template")
template.Copy After:=Sheets(Sheets.Count)
Set newSheet = ActiveSheet
newSheet.Name = "NewCopy"
End Sub
And the Name Manager after a copy:
Here is my answer:
Sub btnCopyTemplate()
Dim template As Worksheet
Dim newSheet As Worksheet
Set template = ActiveWorkbook.Sheets("Template")
template.Copy After:=Sheets(Sheets.Count)
Set newSheet = ActiveSheet
newSheet.Name = "NewCopy"
deleteNames 'Check the sub
End Sub
Sub deleteNames()
Dim theName As Name
For Each theName In Names
If TypeOf theName.Parent Is Worksheet Then
theName.Delete
End If
Next
End Sub
This way you will delete all the names with the scope "worksheet" and keep the "workbook" names
Edit#2
After read the comments here is the update passing the sheet to loop only the "newSheet"
Sub btnCopyTemplate()
Dim template As Worksheet
Dim newSheet As Worksheet
Set template = ActiveWorkbook.Sheets("Template")
template.Copy After:=Sheets(Sheets.Count)
Set newSheet = ActiveSheet
newSheet.Name = "NewCopy"
deleteNames newSheet
End Sub
Sub deleteNames(sht As Worksheet)
Dim theName As Name
For Each theName In Names
If (TypeOf theName.Parent Is Worksheet) And (sht.Name = theName.Parent.Name) Then
theName.Delete
End If
Next
End Sub