Excel 2016 VBA: Set Source Data for a Chart to a Named Table - vba

The title is pretty self-explanatory.
I have a named table, Table_Unit_2_Data, which I would like to set as the source data for a chart that will be created using VBA.
During the recording of a macro I selected the entirety of the table, and inserted a chart. This is the code that I got (Build is the name of the Sheet):
Sub Test()
Range("Table_Unit_2_Data[#All]").Select
ActiveSheet.Shapes.AddChart2(240, xlXYScatterSmoothNoMarkers).Select
ActiveChart.SetSourceData Source:= Range("Build!$Y$1:$AD$2")
End Sub
Well, for one thing, as you can see, a specific $A$1 range is passed into the SetSoureData. This will not work because the range of Table_Unit_2_Data will change.
I attempted this:
With Sheet2.Shapes.AddChart2(240, xlXYScatterSmoothNoMarkers)
.Chart.SetSourceData (Sheet2.Range("Table_Unit_2_Data[#All]"))
End With
But then I get the error "Object Required".
I can't seem to phrase my search queries in such a way as to find relevant answers to this specific question on the internet so I apologize for asking what is likely a redundant question. If someone could help me with this problem I would be greatly appreciative and if anyone has a good article or source online for information regarding the nuances of chart creation within VBA that would also be very helpful.
Thank you.

In addition to what Domenic said (which is correct + would cause the "Object Required" error), your code doesn't make it clear what "Sheet2" is, except that it's the codename of some sheet. From the recorded macro, I can infer that the actual table is on a sheet called "Build", so another possibility to consider is that Sheet2 isn't actually the codename of Sheets("Build"). Again, I can't actually tell from the code provided.
While I do like using sheet codenames, I'd strongly recommend against using them if you're not going to make the names descriptive.
FWIW, there's another way to reference table ranges that's a little more flexible, especially if you're going to be referring to the table elsewhere in the code. Just make a ListObject variable:
Dim UnitTable2 As ListObject
Set UnitTable2 = Sheets("Build").ListObjects("Table_Unit_2_Data")
And you'll be able to reference any part of the table really easily:
Dim rng As Range
'Reference the whole table, including headers:
Set rng = UnitTable2.Range
'Reference just the table data (no headers):
Set rng = UnitTable2.DataBodyRange
'Reference just the data in a single column:
Set rng = UnitTable2.ListColumns("Col1").DataBodyRange
'Reference the headers only
Set rng = UnitTable2.HeaderRowRange

Related

Difficulties with copying text from one word range to another - returns error code "This command is not available"

I am trying to copy contents from a specific range in a Word table, to another range within the same table. I am aware this code is quite messy/simple, but i am currently just trying to get it to work and mapping the different ranges. The current copy/paste method worked well until i added the last range, where it returns "Run-time error '4605'
This command is not available.".
My first attempt was using selection.copy/paste, but that seems to be less efficient (and returned a similar, if not the same, error). I have tried using Rng=Rng2.text, however that somehow only transfers part of the range.
When i round the code in debug step-by-step it works - so it seems like the code is running too fast for the clipboard to follow along or something like that? I suppose i have to use a different method, but currently i am out of ideas (not very experienced with working with ranges in Word) - any ideas?
Note that some of the ranges share cells, which may complicate things. Also, this is my first post on here, so i apologize in advance if it may be a bit messy.
The code:
Sub test()
Set Rng = ActiveDocument.Range(start:=ActiveDocument.Tables(4).Cell(23, 3).Range.start, End:=ActiveDocument.Tables(4).Cell(26, 4).Range.End)
Rng.Copy
Set Rng2 = ActiveDocument.Range(start:=ActiveDocument.Tables(4).Cell(23, 2).Range.start, End:=ActiveDocument.Tables(4).Cell(26, 3).Range.End)
Rng2.Paste
Set Rng = ActiveDocument.Range(start:=ActiveDocument.Tables(4).Cell(22, 4).Range.start, End:=ActiveDocument.Tables(4).Cell(22, 5).Range.End)
Rng.Copy
Set Rng2 = ActiveDocument.Range(start:=ActiveDocument.Tables(4).Cell(22, 3).Range.start, End:=ActiveDocument.Tables(4).Cell(22, 4).Range.End)
Rng2.Paste
Set Rng = ActiveDocument.Range(start:=ActiveDocument.Tables(4).Cell(23, 6).Range.start, End:=ActiveDocument.Tables(4).Cell(26, 6).Range.End)
Rng.Copy
Set Rng2 = ActiveDocument.Range(start:=ActiveDocument.Tables(4).Cell(23, 4).Range.start, End:=ActiveDocument.Tables(4).Cell(26, 5).Range.End)
Rng2.Paste
End sub

PivotCache Refresh from Access

I am automating some Excel file creation from Access. I need help with dynamically resetting the pivotcache for all the pivot tables. The first set of code is me testing working code in Excel. Now I want to translate this so that it runs from Access module.
Sub Update_PTSource()
With Sheets("Pivot")
.PivotTables(1).ChangePivotCache ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:=Sheets("Data").Range("data"))
End With
End Sub
Function pivot_refresh_test()
Dim pt As Variant
Dim wb, ws As Object
Dim strWBName As String
Dim strTabName As String
strWBName = "C:\Users\...\Packaged SKU.xlsb"
strTabName = "Pivot"
Set wb = GetObject(strWBName)
For Each pt In wb.Sheets(strTabName).Pivottables
pt.ChangePivotCache wb.PivotCaches.Create(SourceType:=xlDatabase, SourceData:=wb.Sheets("Data").Range("data"))
pt.RefreshTable
Next pt
End Function
I'm getting error on pt.ChangePivotCache line with error
invalid procedure call or argument
As far as I can see, you've only made one simple error:
xlDatabase is an Excel enum, and since you're using late bindings, you don't have access to it. You can use it's integer value, 1, instead:
For Each pt In wb.Sheets(strTabName).Pivottables
pt.ChangePivotCache wb.PivotCaches.Create(SourceType:=1, SourceData:=wb.Sheets("Data").Range("data"))
pt.RefreshTable
Next pt
I'm anal about using the least code possible when designing solutions so I found a much easier method to what I wanted to do.
My task was to update and refresh the source data of all my pivot tables. There was one source, multiple pivot tables. I created a dynamic named range for my source for this purpose in my template Excel book that Access was writing into. I never save over the template I just used saveas vba to create the filled copy.
However, since I had created a named range and am modifying always the same template file with Access, I don't need to write a program to change my pivotcache. I can just use 'Change Data Source' in Excel ribbon. The vba code gets much easier. It is just a variation of: ThisWorkbook.RefreshAll. No code loops required!
The whole power of my strategy is the formula that creates my named range. =Data!$A$5:OFFSET(Data!$A$5,COUNTA(Data!$A:$A)-1,52). You just set the first cell of your data, and set how many columns there are for your fields, the rows are automatically adjusted.
I hope this little rant help whoever navigates here. I've been searching a lot for good dynamic pivot table automation but most of the internet has crap info on this.

VBA - Copy from Closed File paste to next available row on Summary Sheet

This is my first post. Forgive me if i am doing something wrong here. I will be glad to correct any mistakes. I have found the web site to be very valuable as i am a baby in the field of vba. Please have patience with me.
I am a super rookie in VBA. I am learning as i go but have spent a lot of time on this. I find bits and pieces of information on the web but have trouble in putting them all together. I have learned how to make a vba macro that i can select a file and then run other macros.
I am using Excel 2013.
I complete a time sheet every week(sometimes more at end of month) of the hours i work and the projects i work on. I also include on that sheet when i am out and a code for the reason. I would like to copy three sections to a summary sheet.
Cell D1. This cell always has the date beside it. I would like to copy this to the cell in my first row.
Cells F3-L3 are cells where a code is put. I would like to copy this to the second cell in my first row.
The next range of cells aret the last cells with data in columns F-L. These vary as we have different numbers of rows for work orders each time but are always in columns F-L. I would like to copy this to a second row below the corresponding cells in the first.
For the next file I would like to copy to the next available row in summary.
I would like to copy this data so i can figure vacation days, sick days, etc.
I know i'm asking alot but would be extremely grateful for any help.
i'm giving you this as Example, you will still need to modify...
Option Explicit 'forces Programmer to declare variables
Sub Button_To_Copy () 'link this to a button or other action that launchs the sub
Dim Range_to_Copy as Range
Dim Range_Destination as Range
Dim Sheet_Data as worksheet 'sheet from where we pull the data
Dim Sheet_Destination as Worksheet' Summary Sheet
set Sheet_Data = Thisworkbook.Sheets("Sheet1") 'you might have to rename the sheetname accordingly to its name.
set Sheet_Destination = Thisworkbook.sheets("Summary") ' wild guess, correct to your summary sheet name
Set Range_to_Copy = Sheet_Data.Range("D1")
Set Range_Destination = Sheet_Destination.range("A1")
Range_to_Copy.Copy Range_Destination 'this copies from range A to B (basically A.copy B), but i changed variable names to make it easier...
'more code, copies
'you can simplify without variables like this:
'Sheets("Sheet1").Range("D1").Copy Sheets("Summary).Range("A1") <===== does the same as the above coding
End Sub
Note that i never used activate or select, wich macro recorder will badly use all the time, making bad habits to starters.
Also, by referencing hard cell location like "D1", the code is not dynamic, if you add more data, the sub will have to be changed, so use this just as a start maybe

Get Source Range of a PivotTable

I am building a set of reports to be updated daily for some users who are not super savvy when it comes to pivot charts and pivot tables in Excel (2010). I have data from an already automated data pull from our db, but to make that information useful (and more simple to use), I want to generate the pivots using VBA.
I have already generated the pivot tables just fine and can manually manipulate them to create the relevant charts. As I create the tables (all on one sheet), I am labeling them (if that helps solve my problem). Where I am running into trouble is creating the pivot charts, and specifically, setting the data source.
Since the charts are based on pivots that may change in size depending on the data present, I can't just assign a fixed range as the source. Same problem with a named range, as I still don't know what range to assign a name, unless I can assign a PT as a range.
I've tried something like this, but that didn't work, since I'm not looking at an actual 'Range' object:
Dim MyChartObject As ChartObject
Dim MyChart As Chart
'These variables are assigned elsewhere in the code.
Set MyChartObject = wksMainCharts.ChartObjects.Add( _
iChartLeft, iChartTop, iChartWidth, iChartHeight)
Set MyChart = MyChartObject.Chart
MyChart.SetSourceData wksMainPivot.PivotTables(PivotName).SourceData 'Fails; requires Range object
'More code to follow...
I do know that this is a string representation of the wrong range, but I was playing with what I could figure on my own.
Essentially what I want is the opposite of this question, which seeks to find the pivot table at a specified range. I also reviewed this question, but it's not quite what I'm looking for (there are also no answers provided).
Also: I'm asking here for a way to get the range of a PT, which I think would be interesting to know, but ultimately, I just want to create the pivot chart, so if anyone wants to offer a better method than what I've started on, I'm completely open to that as well.
Is this what you are trying to achieve?
Sub Sample()
Dim Chrt As Chart, pvtTbl As PivotTable
Set pvtTbl = ActiveSheet.PivotTables(1)
Set Chrt = ActiveSheet.ChartObjects(1).Chart
Chrt.SetSourceData Source:=pvtTbl.TableRange1
End Sub
So your this line
MyChart.SetSourceData wksMainPivot.PivotTables(PivotName).SourceData
becomes
MyChart.SetSourceData wksMainPivot.PivotTables(PivotName).TableRange1

Subscript out of range Error after renaming sheets

I have done a small project, which consists of 5 excel sheet in, code is working fine and I am getting exact result also, but if I rename sheets from sheet1 to some other name I am getting Subscript out of range Error.
What is the reason for this and what needs to be done to overcome this. Please help.
Below is the code
Public Sub amount_final()
Dim Row1Crnt As Long
Dim Row2Crnt As Long
With Sheets("sheet4")
Row1Last = .Cells(Rows.Count, "B").End(xlUp).Row
End With
Row1Crnt = 2
With Sheets("sheet3")
Row2Last = .Cells(Rows.Count, "B").End(xlUp).Row
End With
There is nothing wrong with the code per se. You will get Subscript out of range error if Excel is not able to find a particular sheet which is quite obvious since you renamed it. For example, if you rename your sheet "Sheet3" to "SheetXYZ" then Excel will not be able to find it.
The only way to avoid these kind of errors is to use CODENAME of the sheets. See Snapshot
Here we have a sheet which has a name "Sample Name before Renaming"
So consider this code
Sheets("Sample Name before Renaming").Range("A1").Value = "Blah Blah"
The same code can be written as
Sheet2.Range("A1").Value = "Blah Blah"
Now no matter how many times you rename the sheet, the above code will always work :)
HTH
Sid
The basic issue is that you are referring to sheets using their common names and not their codenames. Whenever you refer to Sheets("sheet4"), you are relying on the sheet having that name in Excel. Codenames are the names assigned in Visual Basic so the end user does not interact with them/as a developer you can change the Excel names any time you like
Using code names is covered at around 9:40 in this Excel help video. You'll note they are quicker to type than the Excel names as do not require the 'Sheets()' qualifier
I couldn't see Sheets("Sheet1") in your code sample but you can switch to codenames for all sheets very quickly by finding/replacing all examples of e.g. 'Sheets("Sheet2").' with 'Sheet2.'
Refer to each sheet by their code names instead. They are set to Sheet1, Sheet2 etc as default, but you can rename them in the Properties window for each sheet if you want. This way you can write your code like below instead, regardless of what you name the sheets.
With Sheet1
Row1Last = .Cells(Rows.Count, "B").End(xlUp).Row
End With
Row1Crnt = 2
With Sheet2
Row2Last = .Cells(Rows.Count, "B").End(xlUp).Row
End With
etc...
I wanted to share my experience battling this problem. Here is the mistake I committed:
Dim DailyWSNameNew As String
lastrow = Sheets("DailyWSNameNew").Range("A65536").End(xlUp).Row + 1 -- This is wrong as I included a placeholder worksheet name in quotes
Correction:
lastrow = Sheets(DailyWSNameNew).Range("A65536").End(xlUp).Row + 1
This solved it.
I encountered this error earlier today but could not use any solution above, I did however eventually managed to solve it myself.
My situation was that I had a list contained in column A. For each cell with a value I stored the value in a variable, created a new sheet and named the sheet according to the value stored in the variable.
A bit later in the code I tried to select the newly created sheet by using the code:
Sheets(ValueVariable).Select
I encountered the "Subscript out of range" error and I couldn't figure out why. I've used similar code before with success.
I did however solve it by casting the variable as a string. Declaring the variable as a string did not seem to work for me.
So, if anyone else encounter this error and want something to try, perhaps this will work for you:
Sheets(Cstr(ValueVariable)).Select