Excel VBA PivotCaches won't accept source - vba

I created a sub that automatically creates a pivot table based on a source range. The code works fine when the source data is a small range. However, when I run it on some bigger data (110'000 rows) I get run time error 13 (Type Mismatch).
I don't understand why it does this. I can run the exact same code on another range, and all is well???
Does someone have a suggestion why this would happen?
Set rDataRange = wsData.Range("A1").CurrentRegion
' Create the cache
Set PTCache = ActiveWorkbook.PivotCaches.Create( _
SourceType:=xlDatabase, _
SourceData:=rDataRange)

This question appears to be asking (and answering) a very similar question: Type mismatch error when creating a pivot table in Excel with VBA
Are you absolutely sure your reference to the larger range is valid? Are you positive the larger range is not missing a header, doesn't contain an extra blank row or column, doesn't have any bad data?

Related

ChangePivotCache giving type mismatch error

I have a macro that previously reset the cache of two pivot tables without any error. I'm running into a run time error 13 type mismatch for just 1 of the tables and I do not understand why it's suddenly not working. And for just the one table as well when the code is identical for both tables.
Sub refresh_caches()
Dim cpt As PivotTable, chpt As PivotTable
Set ca2 = Sheets("claim edit").Range("A2")
Set cha2 = Sheets("chrg review").Range("A2")
Set cpc = Range(ca2.End(xlToRight), ca2.End(xlDown))
Set chpc = Range(cha2.End(xlToRight), cha2.End(xlDown))
Set cpt = Sheets("Formulas & Pivots").PivotTables("ptClaim")
Set chpt = Sheets("Formulas & Pivots").PivotTables("ptCharge")
cpt.ChangePivotCache ActiveWorkbook. _
PivotCaches.Create(SourceType:=xlDatabase, SourceData:= _
cpc, Version:=xlPivotTableVersion15)
chpt.ChangePivotCache ActiveWorkbook. _
PivotCaches.Create(SourceType:=xlDatabase, SourceData:= _
chpc, Version:=xlPivotTableVersion15)
For Each PivotCache In ActiveWorkbook.PivotCaches
PivotCache.Refresh
Next
End Sub
The run time error is hitting on the changepivotcache code. When I step through and skip to the second code for chpt, it updates that table fine.
Any help would be greatly appreciated.
Edit The error appears after the data source, which is a data connection, is refreshed. I get the same error even when referencing the range directly as the sourcedata. Though if i manually change the data source the pivot table updates just fine.
Whats also odd that when referencing the full range of data directly it will throw the error, but if I do not reference every row it will update the table.
NEW Edit I believe I've identified the line causing my issue, though I do not fully understand why or if this is what caused the issue previously. I narrowed the issue down to the exact cell and it seems to happen whenever any cell in the range contains more than 255 characters. I tested this with additional cells in the range by adding text to the cell and prompted the error, likewise I could prevent the error by ensuring the text of the cell contained no more than 255 chars.
Why is this? I can manually select the data range and use it as my pivotcache but I cannot get the code to do the exact same thing. Found some issues with cells exceeding 255 chars on google but am still baffled as I'm not referencing the cell specifically, just including it in a range. Would really appreciate some insight on this, especially so I can find a workaround for the next time the data pulls a cell value exceeding this limit.
Although I still do not fully understand why the code errors out whenever a cell containing over 255 characters are included in the data range, it does appear to be the cause.
I've implemented a bit of code to simply identify the cells and reduce the text down to the acceptable amount before setting the PivotCache.
Dim c as Range
For each c in Range("SpecialtyClaimEdit") 'the name of my data connection
If Len(c) > 255 Then
c = Left(c, 255)
End If
Next
It seems that excel has a limit of 255 characters for some properties for some reason.
For instance, I was trying to set descriptions for my UDFs (user-defined functions) and I found out that it is limited to 255 characters. Here's my question: Error while setting UDF description in VBA
Also, if you try to write a function with more than 255 characters in one cell excel cannot handle it. Look at this thread: Excel: Use formula longer that 255 characters
What you have now as an answer works but also you need to loop over all of the cells and loose/remove some of the data. I think, it may also work to make a new sheet and refer to the cells in your original sheet (e.g in cell A1 of the new sheet you type ='Formulas & Pivots'!A1). Then, use that sheet in your code. You need to take the address of the pivot table range from the original sheet and then set another range which is the same but in the new sheet.

How to copy data to an existing sheet without losing any data types or formatting

Here's the problem. I tried to build a simple regression test.
I have two sheets linked together and some other vba functionality.
In order to test regularly, I used copy-move-> make a copy and created precise copy of good sheet a then repeated with good sheetb and took a screenshot of how they should look when working correctly after I run my code.
All I have to do is copy in this known data, run the code then check the output against my screenshot. Or so I thought.
When I ran the code lots of things just changed themselves despite the fact that I a coping a range of data forma clone of this sheet. using
range( a ).value = range( b).value '(pseudo-code)
1 thing I had column with age/weight like this 35/12-11 now its formatted as a date and no fiddling with data types can recover it.
HOW CAN I STOOP eXCEL DOING THIS KIND OF MADNESS?
next thing the text i.e. names of people in a general column show up as 0 in the destination column. Why? it is coming from a clone of the one its always come form without a problem.
Can anyone shed light on this. it's devastaing trying to write a olution up agianst this kind of thing, but I''ve already invetsed a lot in it.
Any help gladly accepted
You can try something like this. Just don't forget to declare your variables. This also assumes that Row A is where your information is
With shttocopy
'finds last row with information
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
'finds last column with information
LastColumn = .cells(LastRow , .Columns.Count).End(xlLeft).Row
'copies cells with information regarding the customer information
'pastes those copied cells into the sheet you want the information moved to
.Range(LastRow:LastColumn).Copy _
destSheet.Cells(Rows.Count, "A").End(xlUp).Offset(1)
end with

Excel VBA named range running out of space in refersto

So I have a large suite of code that creates an archive of data in sheets used by employees. Part of what makes this functional is named ranges on each sheet of usable data. In order for the data integrity to remain, I need to copy the named range objects from the archive sheet to its copy. The named ranges are built programatically and function as expected on the sheets. The problem I'm having is when I go to archive the sheet. Here is the code I'm using to handle the named range object:
For Each n In OldSht.Names
NamedRangeRefersTo = n.RefersTo
NamedRange = n.Name
TrimmedName = Right(n.Name, Len(n.Name) - InStr(1, n.Name, "!", vbTextCompare))
OldSht.Names(n.Name).Delete
OldSht.Names.Add Name:=ArchiveNamedRange, RefersTo:=NamedRangeRefersTo
Next n
The strings that grab data from n are used to add the same name object to the new sheet.
The problem I'm having is when a named range is referencing too large of a range when it hits the line Oldsht.Names.Add, it returns error 1004. I figured out it was the size of the referenced range by messing around with it. I haven't found the exact triggering cause, but this code works as-is when I use it on most of the named ranges. On large data sets with a joined data type that results in a very large named range (it would take a long time to explain how the ranges are built in text. It's a group of 8 sub functions with over 2000 lines of code), this results in the 1004 error.
What I'm confused by is why I can build the named range, use the named range, and copy the named range without issues (if I comment out the offending line, it executes perfectly but I lose data integrity). But when I take the referenced range into a code value, delete the old name reference, then add a new name(with a different name) and assign it the same refersto value of the old name, it can have this problem. I don't understand how it would be different doing this rather than just copying/renaming the name object. Unfortunately, I haven't found a workaround as of yet, nor have I found a clear cause of this error other than the fact that when I remove data or use smaller sets of data in test scenarios, I never have the problem. Does anyone have any ideas of what I can do? Does anyone have any ideas how a named range could be referring to a small enough range that it can be created, but using its refersto value to create a new named range could cause errors only when that is referencing a large range?
I wish I could provide some more concrete examples but unfortunately it would be very difficult to scrub enough sensitive info to provide the full code that would be necessary to reproduce my exact scenarios. Any ideas would be much appreciated.
As requested here's where ArchiveNamedRange gets set:
If Len(OldSht.Name) > 21 Then
ArchiveShtName = Left(OldSht.Name, 21) & DatePart("m", Date) & DatePart("d", Date) & DatePart("yyyy", Date)
Else
ArchiveShtName = OldSht.Name & DatePart("m", Date) & DatePart("d", Date) & DatePart("yyyy", Date)
End If
ArchiveNamedRange = ArchiveShtName & NameObjectName & "Test"
NameObjectName is just the name of the type of object and is passed in from another function. I'm not having an issue with the name just fyi. In the most extreme example the ArchiveNamedRange value at debug run time is = "OutageSystemProcedureMMDDYYYYSecurityRedactionTest" so the name might reach 50 and if things get crazier it might run upwards of 60 characters but it won't ever go beyond that or come anywhere near the 255 character limit. Ultimately, I haven't seen ArchiveNamedRange have an invalid value. It's just a string and it always has a value.
Edit-
Through my troubleshooting I've found that my code works when NamedRangeRefersTo has a length of 2075, but does not work when it has a length of 2091. So somewhere between 2075 characters and 2091 characters is a breaking point for assigning a string to RefersTo: in a named range.
So let's just assume there is a character limit for some reason of 2080 (or whatever it actually is between 2075 and 2091). When I initially find and create these named ranges, they are being given a range object. When I am copying the ranges I am copying as a string. Somehow when I pass a ranged object into RefersTo: it accepts characters beyond 2080 but when I pass in a string it does not. Given that this is my only breaking point of a large suite of code I'd rather find a workaround for this than have to re-factor the entire concept of my archive system. If I use a range object for copying the named ranges, their references follow the old Sheet. That means that when I copy the name over it can be "CriticalSystemsTest1" and referto: "CriticalSystemsTest1!$A$2,..." but once I copy that over and rename the archive worksheet (now CriticalSystems562015) the references adjust to be "CriticalSystems562015Test1!$A$2,..."
So I had to copy as a string to avoid that problem (it breaks data on the new sheet). All I really need is a creative way to overcome this character limit issue on my string. Rebuilding the named range from scratch on the new sheet is also not going to work. So I guess if anyone has ideas for how to work around this string size issue or a way of trimming the string while maintaining functionality of the named range, that would be amazing.
Each of these names has a worksheet level scope, so maybe if there's a way of using just the cell address($A$2) in RefersTo: so it doesn't also contain the worksheet reference (SheetName!), that would be a potential solution but I haven't figured out if that's even possible.
The reason the range definitions as strings are so long is that there are many areas within them. So one workaround would be to build up a new Range object area by area. You can use the string address of each area without running into any limits as each area only has a short reference. Using Range.Address gets the cell reference without the sheet reference, so you can create a new Range on a different sheet but with the same cells. Then use Union() to join all the areas and create the new name using the newly built Range instead of a string:
Dim i As Long, oldRange As Range, newRange As Range
Set oldRange = n.RefersToRange
Set newRange = oldSht.Range(oldRange.Areas(1).Address(External:=False))
For i = 2 To oldRange.Areas.Count
Set newRange = Union(newRange, oldSht.Range(oldRange.Areas(i).Address(External:=False)))
Next i
oldSht.Names.Add Name:="ArchiveNamedRange", RefersTo:=newRange
A couple of notes:
For ranges with many areas this is slow. If you can reliably tie down the threshold where you have problems, it would probably be worth testing for this first and only using this workaround where it was needed.
When testing I also ran into problems with using Worksheet.Range("some very long string range reference"), so this limitation isn't confined to named ranges.

Excel Macro Autofilter issue with variable

I have a table of data with the top row being filters, I have a loop that changes which filter needs to be used inside the loop is the variable filterColumn that is being assigned a new value every time the loop runs through.
when i try to use filterColumn to determine which filter will be 'switched on' i get an error
Autofilter method of Range Class Failed
ActiveSheet.Range("$U$83:$CV$1217").AutoFilter Field:=filterColumn, Criteria1:="<>"
What is the correct syntax in order to use a variable to determine which field the filter is in?
Problem Solved I found the solution. I was referencing the filters columns position in terms of the whole worksheet when in fact I should have been referencing what number it was in the group of filters. For example the filter I wanted to change was in 'CF' which is the 84th column but my the filter I wanted to change is the 64th in the group.
Dim filterColumn As Integer
filterColumn = 2
ActiveSheet.Range("$U$83:$CV$1217").AutoFilter Field:=filterColumn, _
Criteria1:="<>"
EDIT: I tried #HeadofCatering's solution and initially it failed. However I filled in values in the referenced columns and it worked (my solution also failed under reverse conditions - make the column headers blank and it fails).
However this doesn't quite mesh with what I've (and probably you've) seen - you can definitely add filters to columns with blank headers. However one thing was consistent in the failures I saw - the filterColumn referenced a column that was outside of Application.UsedRange. You may want to try verifying that the column you are referencing is actually within Application.UsedRange (easy way: run Application.UsedRange.Select in the Immediate Window and see if your column is selected). Since you are referencing a decent amount of columns, it is possible that there are no values past a certain point (including column headers), and when you specify the column to filter, you are actually specifying something outside of your UsedRange.
An interesting (this is new to me as well) thing to test is taking a blank sheet, filling in values in cells A1 and B1, selecting columns A:G and manually adding AutoFilters - this will only add filters to columns A and B (a related situation can be found if you try to add filters to a completely blank sheet).
Sorry for the babble - chances are this isn't even your problem :)
Old solution (doesn't work when conditions described above are used)
I may be overkilling it, but try setting the sheet values as well (note I used a sample range here):
Sub SOTest()
Dim ws As Worksheet
Dim filterColumn As Integer
' Set the sheet object and declare your variable
Set ws = ActiveSheet
filterColumn = 2
' Now try the filter
ws.Range("$A$1:$E$10").AutoFilter Field:=filterColumn, Criteria1:="<>"
End Sub

How to determine the last column(last column with value) using VBA in excel?

I have a question wonder if anyone can help me out.
I'm doing a project that requires to get a summary of tests result. My flow is as follow,
First, I would need to open my collected test results, then creating a pivot table, after setting accordingly to what i need to view, i will copy the table into another spreadsheet. Over at this spreadsheet, it will change some of the names to the required names and finally, it will be copied to the summary sheet. Then i will need to tabulate the summary in % also.
I'm facing with an issue here which is, for my collected test results, when i put it into the pivot table, i cant determine the number of columns that will appear. For example
In on example, we can have
In another case, we can have
If u notice the second image has more columns used.
Therefore, I was wondering if there is any way that you guys can share with me to determine the last available column with details to be copied.
And can i get the number of the last column so that i can get the summary as well since i need to put it in the form of %.
At the moment, i'm using "Range(A1:Z1000000)" which is quite impossible for me to do anything as i cant really find the % manually.
btw, i need it in VBA code.
Will appreciate for all the opinions and options provided! Thank you in advance!
This should do the trick:
Sub test()
Dim maxColumn As Long
'Create the table here
maxColumn = getMaxUsedColumnNumber("PivotTableSheet")
'do what you need with the number
End Sub
Function getMaxUsedColumnNumber(sheetName As String) As Long
With Sheets(sheetName)
getMaxUsedColumnNumber = .Cells.Find(What:="*", after:=.Range("A1"), LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column
End With
End Function
You can use .SpecialCells() as follows:
ActiveSheet.UsedRange.SpecialCells(xlLastCell).Column
Alternatively, take a look at the ColumnRange property of the PivotTable object. It has a Count property which will return the number of columns in the Pivot Table which could also help.