So I'm 90% of the way into creating my first big macro project. Thanks for all your help so far everyone! I've come up against an issue however - which I think should be the last issue I should face before putting the macro into use.
I've written a macro which copies the data presented in a master spreadsheet, creates a new workbook in the target location, then creates a table using the information provided.
What I want to do is use CurrentRegion to allow the data to alter month-to-month. I think the code should go something like this
`GeneratePivotTables Macro
'Converts information stored on sheet "Data" to a table
Dim TABLE As Range
Set TABLE = Sheets("Data").A1.CurrentRegion
Sheets("Data").Listobjects.Add(x1SrcRange, Range("TABLE"), ,1Xyes).Name="Data"
I know this as presented is incorrect, but I'd like some help just parsing this correctly! My aim is to then be able to use the table "Data" to create pivot tables.
The following code converts the CurrentRegion around cell A1 into a table. See if you can modify it for your needs.
Sub ConvertRangetoTable()
Dim rngTable As Range
Set rngTable = Sheets("Data").Range("A1").CurrentRegion
Sheets("Data").ListObjects.Add(xlSrcRange, rngTable, , xlYes).Name = "All_Data"
End Sub
This seems to be sufficient
Sub M_snb()
Sheet1.ListObjects.Add(1, [A1].CurrentRegion, , 1).Name = "snb_001"
End Sub
Related
I use a lot of Vlookup to find prices in a certain file (c:/pricelist.xlsx), using the product code. I would like to simplify it by creating a new VBA function, but it does not work.
Function findprice(codes)
Dim price
Dim pricebook As Workbook
Dim pricesheet As Worksheet
Dim pricerange As Range
Dim coderange As Range
Set pricebook = Workbooks("c:\info\pricelist.xlsx")
Set pricesheet = pricebook.Sheets("Sheet2")
Set pricerange = pricesheet.Range("FF1:FF20000")
Set coderange = pricesheet.Range("H1:H20000")
findprice = Application.Index(pricerange, Application.Match(codes, coderange, 0))
End Function
I can't say for sure since your question didn't include any sample data or explanation of what/why you're trying to do, but I suspect you're over-complicating this is a few ways.
You don't need a custom function to call a worksheet function from the worksheet. Just use the worksheet functions instead.
In this case VLookup is easier and saves a step (as you suggested in your title.)
Instead of referring to huge ranges of two cells, just refer to the whole columns.
Referring to cells in another Excel file is just like any other formula that refers to another file. (More infor here)
You should be able to use something like this on the worksheet:
=VLOOKUP(A1,'c:\info\pricelist.xlsx'!$H:$FF,155,FALSE)
...where A1 is the value to match (ie., codes).
If you do need this is VBA for some reason, it's easy to adapt just like your sample function.
More Information:
Office Support : Create or change a cell reference
Office Support : Create an external reference (link) to a cell range in another workbook
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.
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
Currently I'm creating a macro that reads data from a table column, Asset No. The data is obtained through drop-down menu via data validation from another table in another sheet, DieMaster.
It will then perform Index and Match to find the matching data from DieMaster and insert it into Description column.
In addition, Upon obtaining data, the table column will then copy and paste as value to get the data only. That way the formula won't slow down filter searches.
This is what I have come up with.
Sub convert()
Dim osh As Worksheet
Set osh = ActiveSheet
osh.Range("ProjectEntry[Description]").Formula = "=IF(ISNA(INDEX(DieMaster,MATCH(B4,DieMaster[Asset No],FALSE),2)),"""",INDEX(DieMaster,MATCH(B4,DieMaster[Asset No],FALSE),2))"
osh.Range("ProjectEntry[Description]").Copy
osh.Range("ProjectEntry[Description]").PasteSpecial xlPasteValues
End Sub
I have tested the macro and it works perfectly. However the issue I have now is trying to assign the macro to Asset No column. My plan is to have it so that when a value is selected in a cell within the Asset No column via aforementioned drop-down menu, it will automatically show me the data for description.
Since I cannot assign macro to column using the traditional method, is there an alternative?
You can use the Worksheet_Change Event to accomplish this:
Private Sub Worksheet_Change(Target as Range)
If Not Intersect(Target, Me.ListObjects("ProjectEntry").ListColumns("AssetNo").DataBodyRange) Is Nothing Then
With Me.Range("ProjectEntry[Description]")
.Formula = "=IF(ISNA(INDEX(DieMaster,MATCH(B4,DieMaster[Asset No],FALSE),2)),"""",INDEX(DieMaster,MATCH(B4,DieMaster[Asset No],FALSE),2))"
.Value = .Value
End With
End If
End Sub
My syntax may be slightly off (since I am not on my normal computer), but it will get you close enough to tweak on your own.
I need a way to programatically adjust an entire row in an excel table based on the ActiveCell, irrespective of what table it's in or where the table is. I was using
ActiveSheet.ListObjects(1).ListRows(ActiveCell.Row - 1).Range.Select
Selection.Style = "Good"
but upon shifting the table down five rows, it now applies the action down a further five rows from the ActiveCell.
I've tried finding a way to replace the - 1 with some sort of - .HeaderRowRange.Row but nothing happens when I activate the macro.
You can take advantage of the ActiveCell.ListObject property. This makes it more flexible, e.g., if there's two tables in a worksheet:
Sub FormatActiveTableRow()
Dim lo As Excel.ListObject
Set lo = ActiveCell.ListObject
If Not lo Is Nothing Then
Intersect(ActiveCell.EntireRow, lo.Range).Style = "Good"
End If
End Sub
If I understood the problem correctly, try using the following code and report back:
ActiveSheet.ListObjects(1).ListRows(ActiveCell.Row - ActiveSheet.ListObjects(1).HeaderRowRange.Row).Range.Select