Application-defined or object-defined error - vba

So I have a sheet called "Dashboard" that I have several charts on, but every week I'm adding data to the tables these charts are based on. The second sheet that has the data for this table is "Historical Totals" and the data I want is in columns A through E (this includes labels and headers). I'm trying to automate the charts updating, and I don't quite know why this isn't working. Here is the code I have so far:
Sheets("Dashboard").Select
ActiveSheet.ChartObjects("Chart 4").Activate
ActiveChart.SetSourceData Source:=Sheets("Historical Totals").Range("A1", Range("E1").End(xlDown))
I've tried seperating our the range, and it is selecting the appropriate data, so I don't really know where I'm making the mistake.

try the following. You need to reference the data sheet every time you use Range:
Sheets("Dashboard").ChartObjects("Chart 4").Activate
ActiveChart.SetSourceData _
Source:=Sheets("Historical Totals").Range(Sheets("Historical Totals").Range("A1"), _
Sheets("Historical Totals").Range("E1").End(xlDown))

Assuming you only have the table in the worksheet "Historical Totals" I would usually go xlUp rather than xlDown but the following is effectively the same as Philip A Barnes's answer:
Sub setArea()
With Excel.ActiveWorkbook
'.Sheets("Dashboard").Select '<==no need to select for the code to execute
.Sheets("Dashboard").ChartObjects("Chart 1").Activate
End With
With Excel.ActiveWorkbook.Sheets("Historical Totals")
Excel.ActiveChart.SetSourceData _
Source:=.Range( _
.Cells(1, 1), _
.Cells(.Cells(.Rows.Count, 5).End(Excel.xlUp).Row, 5) _
)
End With
End Sub

Related

Excel VB Advanced Filter Copy with Condition

I am trying to put a condition on each row copied. I want all uniques but only if they also have a specific value in another field.
This is what I have to grab all uniques (and it works) but I can't figure out how to get only the rows with a specific value in column J.
r1.Columns(20).AdvancedFilter xlFilterCopy, , Sheet11.Range("A1"), unique:=True
I have tried doing a CriteriaRange but I can't seem to get the syntax correct for it. Additionally I thought about an If statement but logically in my head it means it would fire off the whole list every time it has a true statement, not on a per row basis.
Here is how I thought it might work. But I get a type mismatch error.
r1.Columns(20).AdvancedFilter xlFilterCopy, r1.Columns(10).Value = "November", Sheet11.Range("A1"), unique:=True
Thoughts?
First of all, your Criteria Range should be just that - a Range with the header corresponding to the column to be filtered, and criteria underneath. For example, D1:D2 in this snapshot:
Secondly, you won't be able to copy just a single column (20) while filtering another column (10) in the same step.
You can tweak the Advanced Filter to
First filter the entire list in place based on the criterion provided
And then copy the visible cells in the column in question
Something like this (change Sheet and Range references as needed):
Sub MyFilter()
Dim lastRow As Long
With Sheet1
lastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
.Range("A1:B" & lastRow).AdvancedFilter _
Action:=xlFilterInPlace, CriteriaRange:=.Range("D1:D2"), Unique:=True
With .Range("B1:B" & lastRow).SpecialCells(xlCellTypeVisible)
.Copy Sheet2.Range("A1")
End With
.ShowAllData
End With
End Sub
To be able to keep the other parts of the code that worked perfectly. I added a hidden sheet and wrote a macro to copy the filtered results out to the new hidden sheet. Then I ran my original code against the filtered data on that hidden sheet.
Sub FilterLiveToDataSheet()
' Unhide Required Sheets
Sheets("Original-Data").Visible = True
Sheets("Filtered-Data").Visible = True
' Delete Old Data
Sheets("Filtered-Data").Select
Cells.Select
Selection.ClearContents
' Copy Filtered Data
Sheets("Original-Data").Select
Range("TBL_ATTR_Spend[[#Headers],[HeaderName]]").Select
Selection.AutoFilter
ActiveSheet.ListObjects("TBL_ATTR_Spend").Range.AutoFilter Field:=10, _
Criteria1:="Delta"
Cells.Select
Selection.Copy
' Paste to Data Sheet
Sheets("Filtered-Data").Select
Cells.Select
ActiveSheet.Paste
' Unfilter Original Data Page
Sheets("Original-Data").Select
Range("TBL_ATTR_Spend[[#Headers],[HeaderName]]").Select
Selection.AutoFilter
' Hide Required Sheets
Sheets("Original-Data").Visible = False
Sheets("Filtered-Data").Visible = False
' Go to Results Sheet
Sheets("Results").Select

Macro to Filter Data table on multiple criteria based on specific cell value

I tried to record a macro to filter a data table based on the values of 2 cells. It only worked the first time because VBA recorded the cell value instead of the cell reference. I have not been able to figure out how to alter the code to do the following:
Change the filter selection when the cell value changes
have the filter selection change without navigating to the worksheet containing the data table.
The worksheet where the reference cells are located is called "Cost Estimator" and the worksheet with the data table is "AR_BOM"
The table name is "BOM_Table"
Here is the code that was recorded:
Sub Filter_AR_BOM()
'
' Filter_AR_BOM Macro
'
'
Range("E25").Select
Selection.Copy
Sheets("AR_BOM").Select
ActiveSheet.ListObjects("BOM_Table").Range.AutoFilter Field:=4, Criteria1:= _
"Line 11"
Sheets("Cost Estimator").Select
Range("J10").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("AR_BOM").Select
ActiveSheet.ListObjects("BOM_Table").Range.AutoFilter Field:=13, Criteria1 _
:="12197118"
Sheets("Cost Estimator").Select
End Sub
Any help is greatly appreciated. I've been trying different things from forums for almost 2 days and don't seem to be making any headway. I'm an extreme macro/vba novice, so I know that doesn't help anything.
Here's a start at least. The code needs to go in the Cost Estimator sheet module
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$E$25" Or Target.Address = "$J$10" Then
Sheets("AR_BOM").ListObjects("BOM_Table").Range.AutoFilter Field:=4, Criteria1:=Range("E25").value
Sheets("AR_BOM").ListObjects("BOM_Table").Range.AutoFilter Field:=13, Criteria1:=Range("J10").value
End If
End Sub

Concat tables in different excel worksheet

Question
I'm trying to do something that may be very simple using Excel but I can't find how to do it.
I have several worksheets, each one contains a single table. To give you an example, here are two of my worksheets :
First worksheet. Please note that lines are green.
Some data. Without 's', sorry :-)
Second one. Lines are grey but cells can be red. Headers are NOT the same
I would like to :
merge those tables into another worksheet
keep style formatting (line color, etc)
when I update a table, the merged one should update too (may be a macro)
Here is a possible output :
Note that same headers are correctly merged.
Can I do this with Excel ? I know that I can do a query (UNION ALL) but doing this doesn't preserve style formatting.
Edit 1
I've tried to build the table using microsoft queries. Here is my query :
SELECT * FROM `C:\Users\cflodrops\Downloads\comptes.xlsx`.`Purchases$` `Purchases$`
UNION ALL
SELECT * FROM `C:\Users\cflodrops\Downloads\comptes.xlsx`.`Sales$` `Sales$`
UNION ALL
SELECT * FROM `C:\Users\cflodrops\Downloads\comptes.xlsx`.`Trades$` `Trades$`
UNION ALL
SELECT * FROM `C:\Users\cflodrops\Downloads\comptes.xlsx`.`Transfers$` `Transfers$`
This request works great, here is the result :
But I still have issues :
style formatting is incorrect (background colors and numbers format)
datas are not synchronized between arrays. It's not an issue, I can create a macro to execute the request whenever I click on a button.
you have a few problems...union can work. Assuming union path from your first edit.
Add placeholder columns on both sheets to allow proper union, OR force placeholders columns in with your t-sql queries.
Add columns to each sheet representing the source OR add these in with your t-sql queries. e.g. 'Sheet1'
On your unioned sheet with the results, add conditional formatting, where the row with the cell of the source type is evaluated, then the entire row is formatted as necessary. e.g. cell A2 has 'Sheet1', then row A is colored green.
If i understand you well, you want to:
copy data preserving formatting from existing sheets and put them into another sheet (new or existing; let's call it "merged data"),
keep one-way synchronization betweem source sheets and "merged sheet", which means when source sheet is changing, a "merged sheet" changes too.
The answer for both issues is YES depending on a way you choose to merge/synchronize/display data...
Method #1 - using copy & paste data one below another
This method will preserve formatting, but there's no chance to update destination table (sheet) when source data have been changed. You'll need to create it every time you want to see merged data.
Method #2 - using Range.CopyFromRecordset method together with UNION statement
If you want to use this method, you have to change your data set into model of relational database. There's no chance for preserving source formatting, but "merged sheet" may be quickly reloaded (a'ka updated).
Both methods of copying data between sheets you'll find here: Copy Data Between Excel Sheets using VBA, but this tip does not provide information about copying data within its originall format. So, i decided to clarify how to achieve that and show/provide code which create destination sheet with merged data.
In my example i have 3 sheets. First and second sheet is used as source of data and the 3. one is used to display merged data. Only 3 columns (A-C) contain data, so ranges to copy are hard-coded.
Option Explicit
'method #1
Private Sub CopyWithFormatting(srcSh As Worksheet, dstSh As Worksheet, Optional sCol As String = "A")
Dim e1 As Long, e2 As Long
On Error GoTo Err_CopyWithFormatting
'last row in src and dst sheet
e1 = srcSh.Range(sCol & srcSh.Rows.Count - 1).End(xlUp).Row
e2 = dstSh.Range(sCol & dstSh.Rows.Count - 1).End(xlUp).Row + 1
'do not refresh screen
Application.ScreenUpdating = False
'copy defined range
srcSh.Range("A2:C" & e1).Copy
'paste below existing data
With dstSh.Range("A" & e2)
.PasteSpecial xlPasteAllUsingSourceTheme
.PasteSpecial xlPasteFormats
.PasteSpecial xlPasteValidation
End With
Exit_CopyWithFormatting:
On Error Resume Next
'restore default settings
With Application
.CutCopyMode = False
.ScreenUpdating = True
End With
Exit Sub
Err_CopyWithFormatting:
MsgBox Err.Description, vbExclamation, "Err no. " & Err.Number
Resume Exit_CopyWithFormatting
End Sub
How to use it?
Sub TestMethod1()
Dim CopiedSheet As Worksheet, DestSheet As Worksheet
'as i mentioned -> 3. sheet is used to merge data
'you can change it by using sheet's name or its index
Set DestSheet = ThisWorkbook.Worksheets(3)
'copy data from sheets into destination sheet
For Each CopiedSheet In ThisWorkbook.Worksheets
'ignore destination sheet
If CopiedSheet Is DestSheet Then GoTo SkipNext
CopyWithFormatting CopiedSheet, DestSheet
SkipNext:
Next
End Sub
Finall note: Feel free to change above code to your needs.
In the third sheet I would have a macro in the Activate event, that pulls the data from from the first two sheets. I would add a hidden column in the third sheet that contains to originating sheet. In your conditional formatting for the third sheet you would need to base your formatting on the value in the hidden column. I can post a sample to clarify if you wish.
EDIT: Added sample
Private Sub Worksheet_Activate()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Dim Sheet1 As Worksheet
Dim Sheet2 As Worksheet
Dim Sheet3 As Worksheet
Set Sheet1 = Worksheets(1)
Set Sheet2 = Worksheets(2)
Set Sheet3 = Worksheets(3)
Sheet1.Range("A2:D101").Copy
Sheet3.Cells(2, 1).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
Sheet2.Range("A2:D101").Copy
Sheet3.Cells(102, 1).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
Sheet3.Cells(1, 1).Select
ActiveWorkbook.Worksheets("Sheet3").AutoFilter.Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet3").AutoFilter.Sort.SortFields.Add Key:=Range _
("A1:A201"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
With ActiveWorkbook.Worksheets("Sheet3").AutoFilter.Sort
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
Here is an example file.
ConcatSheets Example.xlsm

How to select data range dynamically for pivot table

I have searched this topic exhaustively however I am struggling to find a solution which works for my macro. I need the source data for a pivot table to include all rows (containing data) on a sheet. The amount of rows will change daily.
Here is what I've got so far:
Sheets("Sheet1").Select
Sheets("Sheet1").Name = "RAW_DATA"
Range("A1").Select
Sheets.Add
ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:= _
"RAW_DATA!R1C1:R159C24", Version:=xlPivotTableVersion14).CreatePivotTable _
TableDestination:="Sheet4!R3C1", TableName:="PivotTable1", DefaultVersion _
:=xlPivotTableVersion14
Sheets("Sheet4").Select
Cells(3, 1).Select
With ActiveSheet.PivotTables("PivotTable1").PivotFields("Asset")
.Orientation = xlRowField
.Position = 1
End With
The values which represent my pivot tables source data are RAW_DATA!R1C1:R159C24. The problem is that I need this range to dynamically increase or decrease depending on the size of the populated source data range.
First of all, you might be able to easily solve your problem by just setting the columns as your datarange (E.g. RAW_DATA!$A:$X).
When the data is appended a simple update on the pivot will include new data or exclude the data that is no longer there.
That said, here's a VBA solution:
This Example will change the source data for PivotTable1 on Sheet1 to be "RAW_DATA!$A$1:$X$ whatever the last row is"
Sub ChangePivotData()
Dim lastrow as double
lastrow = Worksheets("RAW_DATA").Range("A" & Rows.Count).End(xlUp).Row
With Worksheets("Sheet1").PivotTables("PivotTable1")
.ChangePivotCache ActiveWorkbook.PivotCaches.Create( _
SourceType:=xlDatabase, _
SourceData:="RAW_DATA!A2:X" & CStr(lastrow), _
Version:=xlPivotTableVersion14)
End With
End Sub
That is the core of it. However, you might want to check for blank column headers to do some error prevention, automatically refresh the table after the new cache has been set, etc.
More extensive example can be found here:
http://www.thespreadsheetguru.com/the-code-vault/2014/7/9/change-a-pivot-tables-data-source-range
Enjoy :)
You can use the below if your data is the only thing in the sheet
Worksheets("RAW_DATA").Usedrange
and the corresponding range address
Worksheets("RAW_DATA").Usedrange.Address
Hope this helps

Loops with advanced filter, new criteria every Loop

I have this code:
Sub omgifthisworks()
Sheets("data").Select
Columns("A:A").AdvancedFilter Action:=xlFilterInPlace, CriteriaRange:= _
Sheets("log").Range("A1:A4"), Unique:=False
Sheets("Data").Select
Sheets("Data").Copy After:=Sheets(3)
ActiveSheet.Name = Sheets("banks").Range("A2").Value
enter code here
It's function is pretty basic. Is it possible to create a Loop where this code will create as many new worksheets as I have cells in column "A" in my "banks" worksheet?
Is it also possible to have the loop move the filter criteria on column to the right and select only as many cells as there is data?
The end result that I'm hoping to achieve is code that will create many new sheets of data with different names that have data inside which is filtered by new criteria every time.
For your first question about looping through, go here:
http://www.excel-easy.com/vba/loop.html
http://msdn.microsoft.com/en-us/library/eked04a7.aspx
For your second:
Sheets.Add After:=ActiveSheet
ActiveSheet.Name = [name you want]
I've used code like this to do something similar what you're talking about.
origSh as the Worksheet containing the original data to filter.
filterSh is a Worksheet containing the data for the Advanced Filter. Row 1 contains column headers to filter on; row 2 contains the data criteria to filter.
The procedure loops through the columns of filterSh and filters the data in origSh by the given criteria, copying the filtered data to new sheets placed at the end of the workbook.
Sub FilterToSheets(origSh As Worksheet, filterSh As Worksheet)
Dim filterRng As Range
Dim newSh As Worksheet
Set newSh = filterSh
For Each filterRng In filterSh.UsedRange.Columns
Set newSh = ActiveWorkbook.Worksheets.Add(after:=newSh)
newSh.Name = filterRng.Cells(2).Text
origSh.UsedRange.AdvancedFilter _
Action:=xlFilterCopy, _
criteriarange:=filterRng, _
copytorange:=newSh.Range("A1"), _
unique:=False
Next
End Sub
This should hopefully give you a leg up to write something that fits your example.