Inject two ranges into SQL Command Text, Excel VBA - sql

Having some trouble with my macro where I need to inject two ranges into a SQL query. The reason being that it exceeds Excel's character limit for 1 cell, so I have used a formula to split the query between 2 (keeping in mind spaces for the split to keep the syntax correct).
However, my VB to inject both the ranges together is not working so it's clear there's something I'm not considering correctly. The error is Run-time error 1004: Application-defined or object-defined error
Here's how it currently appears:
With ActiveWorkbook.Connections("Qry").ODBCConnection
.CommandText = Range("Cell1") & Range ("Cell2")
End With
I have also tried to add .Value, as well as declaring the ranges before and then calling them. Note: Cell1 is the name I have given the cell.
When using Debug.Print on Range("Cell1") & Range ("Cell2"), the statement is jumbled, Cell1 starts midway before joining correctly into Cell2, then the beginning part of Cell1 abruptly starts again.

Immediate window is limited to 200 lines so debug.print won't show the full text. Write the sql to a file and maybe test it in database client.
Dim sql as string, ts
sql = Range("Cell1") & Range("Cell2")
With CreateObject("Scripting.FileSystemObject")
Set ts = .createTextFile("debug.sql")
ts.Write sql
ts.Close
End With

Related

changeable/varied named range WHERE search in Excel SQL

There have been a few posts about this, but cannot find anything relating specifically to my problem.
I want to have a WHERE search on a named range within VBA where the range is changeable e.g not simply A1:A10, but A1:End
I have tried the below, but only the last cell within the range is used in the SQL WHERE results
Set Brokers = Sheets("Brokers").Range("A2").End(xlDown)
Dim r As Variant
r = Brokers.Value
....
WHERE c_broker = '" & r & "'"
I have also tried the below, but am getting a "type mismatch" error
WHERE c_broker IN( '" & Join(Application.Transpose(Sheets("Brokers").Range("A2").End(xlDown).Value), "','") & "')"
If anyone could help - or let me know if not possible at all - that would be great!
Thanks!
EDIT:
To further explain this, I have a range in sheet "Brokers" starting from A2 going down where the end can change depending on user input e.g it can be A2:A10 or A2:A15. I want SQL to pick up on this range at whatever it currently is, which is why I've been trying to use End(xlDown) in the VBA. I have tried changing the above to the below, but am having an "Application-defined or object-defined error"....the same goes when I add this in the SQL WHERE line - unless I am doing something incorrect with the below?
Set Brokers = Sheets("Brokers").Range("A2", Range("A2").End(xlDown))

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.

VBA Runtime error 1004 when trying to access range of sheet

I am building a small vba script that is merging tables from several workbook into one single worksheet of another workbook. The error is raised when I try to set the destination range's value:
wksPivotData.Range(wksPivotData.Cells(CurrentRow, 1)).Resize(tbl.ListRows.Count, tbl.ListColumns.Count).Value = _
tbl.Range.Value
The error: "Run-time error '1004': Application-Defined or object-defined error"
I went through similar questions, and the general answer is what I found in this one: The selected cell belongs to another worksheet than the one desired.
While this makes complete sense, I still can't figure why my code breaks as I'm only using numerical reference (CurrentRow is a Long) and Resize, which should prevent me from doing such a mistake.
Additionally, I ran a couple quick tests in the Immediate window and it turns out that while the worksheet wksPivotData exists and I can access its name and a cell value, the range function simply doesn't work:
Debug.Print wksPivotData.Name
PivotData
Debug.Print wksPivotData.Cells(1, 1).Value
123
Both of those work but the next one doesn't:
Debug.Print wksPivotData.Range(1, 1).Value
Your last line, Debug.Print wksPivotData.Range(1, 1).Value won't print because you're misuing Range(). I assume you want A1?
When using Range(1,1), you're referring to a non-existent range. If you want to do cell A1, you need
With wksPivotData
myData = .Range(.Cells(1,1),.Cells(1,1)).Value
End with
Since you're using multiple worksheets, I'd use the with statement as above. Another way to write the same thing is wksPivotData.Range(wksPivotData.Cells(1,1),wksPivotData.Cells(1,1)) (You need to explicitly tell Excel what sheet you want to refer to when using Range() and cells().
Finally, for your resize, if I recall correctly, you're going to have to add the same Cell() twice in your range:
wksPivotData.Range(wksPivotData.Cells(CurrentRow, 1),ksPivotData.Cells(CurrentRow, 1)).Resize(tbl.ListRows.Count, tbl.ListColumns.Count).Value = _
tbl.Range.Value
Or, for the same thing, but different way of doing it:
With wksPivotData
.Range(.Cells(currentRow, 1), .Cells(currentRow, 1)).Resize(tbl.ListedRows.Count, tbl.ListColumns.Count).Value = tbl.Range.Value
End With

Long nested IF statement creates runtime error 1004 in Excel VBA

I have a formula that works perfectly well in a spreadsheet, but when I try to automate the creation of the formula using VBA, I get the 1004 run time error.
I have a 3 stage process, each with a start and finish date (so 6 separate date columns). This formula looks at the series dates and calculates the time lost between each stage using the NETWORKDAYS function.
I thought the simple way to overcome this problem was to record a macro of me pasting this formula into a cell, which would generate the required VBA code that I could then adapt, but even using this method causes the 1004 error.
I'm wondering whether it's the length of the formula that's the problem? I've tried replacing the double quotation marks with & Chr(34) & Chr(34) & and I've tried assigning the formula to a variable. I can get it to work if I add it as text using .value instead of .formulaR1C1, or if I add an apostrophe to the start of the formula string. It appears to be the fact that its a formula that causes the problem. Any help is greatly appreciated.
The formula from the cell in the spreadsheet:
=IF(AND(I2="",J2="",K2="",L2=""),"",IF(AND(G2="",H2="",K2="",L2=""),"",IF(AND(G2="",H2="",I2="",J2=""),"",IF(AND(H2<>"",I2<>"",J2<>"",K2<>""),IF(NETWORKDAYS(H2,I2)-2+NETWORKDAYS(J2,K2)-2<1,"",NETWORKDAYS(H2,I2)-2+NETWORKDAYS(J2,K2)-2),IF(AND(H2<>"",I2<>""),IF(NETWORKDAYS(H2,I2)-2<1,"",NETWORKDAYS(H2,I2)-2),IF(AND(H2<>"",K2<>""),IF(NETWORKDAYS(H2,K2)-2<1,"",NETWORKDAYS(H2,K2)-2),IF(AND(J2<>"",K2<>""),IF(NETWORKDAYS(J2,K2)-2<1,"",NETWORKDAYS(J2,K2)-2),"")))))))
The code that the macro records when I enter the formula into the cell:
ActiveCell.FormulaR1C1 = _
"=IF(AND(RC[-10]="""",RC[-9]="""",RC[-8]="""",RC[-7]=""""),"""",IF(AND(RC[-12]="""",RC[-11]="""",RC[-8]="""",RC[-7]=""""),"""",IF(AND(RC[-12]="""",RC[-11]="""",RC[-10]="""",RC[-9]=""""),"""",IF(AND(RC[-11]<>"""",RC[-10]<>"""",RC[-9]<>"""",RC[-8]<>""""),IF(NETWORKDAYS(RC[-11],RC[-10])-2+NETWORKDAYS(RC[-9],RC[-8])-2<1,"""",NETWORKDAYS(RC[-11],RC[-10])-2+NETWORKDAYS(RC[" & _
"8])-2),IF(AND(RC[-11]<>"""",RC[-10]<>""""),IF(NETWORKDAYS(RC[-11],RC[-10])-2<1,"""",NETWORKDAYS(RC[-11],RC[-10])-2),IF(AND(RC[-11]<>"""",RC[-8]<>""""),IF(NETWORKDAYS(RC[-11],RC[-8])-2<1,"""",NETWORKDAYS(RC[-11],RC[-8])-2),IF(AND(RC[-9]<>"""",RC[-8]<>""""),IF(NETWORKDAYS(RC[-9],RC[-8])-2<1,"""",NETWORKDAYS(RC[-9],RC[-8])-2),"""")))))))"
Consider:
Sub EvilFormula()
Dim st As String, DQ As String
DQ = Chr(34) & Chr(34)
st = "=IF(AND(I2=~,J2=~,K2=~,L2=~),~,IF(AND(G2=~,H2=~,K2=~,L2=~),~,IF(AND(G2=~,H2=~,I2=~,J2=~),~,IF(AND(H2<>~,I2<>~,J2<>~,K2<>~),IF(NETWORKDAYS(H2,I2)-2+NETWORKDAYS(J2,K2)-2<1,~,NETWORKDAYS(H2,I2)-2+NETWORKDAYS(J2,K2)-2),IF(AND(H2<>~,I2<>~),IF(NETWORKDAYS(H2,I2)-2<1,~,NETWORKDAYS(H2,I2)-2),IF(AND(H2<>~,K2<>~),IF(NETWORKDAYS(H2,K2)-2<1,~,NETWORKDAYS(H2,K2)-2),IF(AND(J2<>~,K2<>~),IF(NETWORKDAYS(J2,K2)-2<1,~,NETWORKDAYS(J2,K2)-2),~)))))))"
st = Replace(st, "~", DQ)
ActiveCell.Formula = st
End Sub
Here we first construct a String that represents the formula, but uses tildas in place of pairs of double-quotes. We replace the tildas and deposit the formula.I use this to avoid migraine headaches.

Run time error '1004' Unable to get the Match propertyof the WorksheetFunction class

In my macro, I have the following code :
i = Application.WorksheetFunction.Match(str_accrual, Range(Selection, Selection.End(xlToRight)), 0)
where 'str_accrual' is a string captured earlier to this line and the Range selected is in a single row say from "A1" to "BH1" and the result will be a number which is the position of that string in that range selected.
When I run the macro, I get the error:
Run time error '1004' Unable to get the Match propertyof the WorksheetFunction class
But when I run the macro line by line using (F8) key, I don't get this error but when I run the macro continuously I get the error. Again, if the abort the macro and run it again the error doesn't appear.
I tried several times. It seems that if there is no match, the expression will prompt this error
if you want to catch the error, use Application.Match instead
Then you can wrap it with isError
tons of posts on this error but no solution as far as I read the posts. It seems that for various worksheet functions to work, the worksheet must be active/visible. (That's at least my latest finding after my Match() was working randomly for spurious reasons.)
I hoped the mystery was solved, though activating worksheets for this kind of lookup action was a pain and costs a few CPU cycles.
So I played around with syntax variations and it turned out that the code started to work after I removed the underscore line breaks, regardless of the worksheet being displayed. <- well, for some reason I still had to activate the worksheet :-(
'does not work
'Set oCllHeader = ActiveWorkbook.Worksheets("Auswertung").Cells(oCllSpielID.Row, _
Application.Match( _
strValue, _
ActiveWorkbook.Worksheets("Auswertung").Range( _
oCllSpielID, _
ActiveWorkbook.Worksheets("Auswertung").Cells(oCllSpielID.Row, lastUsedCellInRow(oCllSpielID).Column)), _
0))
'does work (removed the line breaks with underscore for readibility) <- this syntax stopped working later, no way around activating the worksheet :-(
Set oCllHeader = ActiveWorkbook.Worksheets("Auswertung").Cells(oCllSpielID.Row, Application.Match(strValue, ActiveWorkbook.Worksheets("Auswertung").Range(oCllSpielID, ActiveWorkbook.Worksheets("Auswertung").Cells(oCllSpielID.Row, lastUsedCellInRow(oCllSpielID).Column)), 0))
In the end I am fretting running into more realizations of this mystery and spending lots of time again.
cheers
I was getting this error intermittently. Turns out, it happened when I had a different worksheet active.
As the docs for Range say,
When it's used without an object qualifier (an object to the left of the period), the Range property returns a range on the active sheet.
So, to fix the error you add a qualifier:
Sheet1.Range
I had this issue using a third-party generated xls file that the program was pulling from. When I changed the export from the third-party program to xls (data only) it resolved my issue. So for some of you, maybe there is an issue with pulling data from a cell that isn't just a clean value.
I apologize if my nomenclature isn't great, just a novice to this.
That is what you get if MATCH fails to find the value.
Try this instead:
If Not IsError(Application.Match(str_accrual, Range(Selection, Selection.End(xlToRight)), 0)) Then
i = Application.Match(str_accrual, Range(Selection, Selection.End(xlToRight)), 0)
Else
'do something if no match is found
End If
Update
Here is better code that does not rely on Selection except as a means of user-input for defining the range to be searched.
Sub Test()
Dim str_accrual As String
Dim rngToSearch As Range
str_accrual = InputBox("Search for?")
Set rngToSearch = Range(Selection, Selection.End(xlToRight))
If Not IsError(Application.Match(str_accrual, rngToSearch, 0)) Then
i = Application.Match(str_accrual, rngToSearch, 0)
MsgBox i
Else
MsgBox "no match is found in range(" & rngToSearch.Address & ")."
End If
End Sub
I used "If Not IsError" and the error kept showing. To prevent the error, add the following line as well:
On Local Error Resume Next
when nothing is found, Match returns data type Error, which is different from a number. You may want to try this.
dim result variant
result = Application.Match(....)
if Iserror(result)
then not found
else do your normal thing