Cannot use Application.Evaluate() for CUBEVALUE function - vba

Dear MS Excel wizards =)
Recently I'm developing a UserForm for Budget file, to bring all basic controls to one place and ease the life of users. My initial idea was calculating all primary values (starting num of Students, finishing num of Students...) in this form and feed to Budget file formulas as values. For some calculations, I have to address ThisWorkbookDataModel, therefore I was planning to use Application.Evaluate()
Yet it fails with case like this:
m1 = Application.Evaluate("=CUBEVALUE(""ThisWorkbookDataModel"",CUBEMEMBER(""ThisWorkbookDataModel"",{""[DimDate].[1.Year].&[" & mYear & "]"",""[DimDate].[3.MonthCalendarTrue].&[" & mMonth & "]""}),CUBEMEMBER(""ThisWorkbookDataModel"",""[Measures].[mQofStudents]""),CUBEMEMBER(""ThisWorkbookDataModel"",{""[DimCampus].[Burleigh]""}))")
As a workaround, I evaluate this formula on the worksheet first:
Range("AvgStudStartValBH").Formula = "=CUBEVALUE(""ThisWorkbookDataModel"",CUBEMEMBER(""ThisWorkbookDataModel"",{""[DimDate].[1.Year].&[" & mYear & "]"",""[DimDate].[3.MonthCalendarTrue].&[" & mMonth & "]""}),CUBEMEMBER(""ThisWorkbookDataModel"",""[Measures].[mQofStudents]""),CUBEMEMBER(""ThisWorkbookDataModel"",{""[DimCampus].[Burleigh]""}))"
Yet this really creates inconveniences in refreshing of the result in UserForm.
What I found while debugging this Application.Evaluate() issue is that if I cut away last CUBEMEMBER(), it works! So maybe Application.Evaluate() has a limit in symbols?
If so, is there any other workaround except pasting this into Excel worksheet to evaluate there before getting this to the form?

Related

VBA coding for Sumproduct() function with condition and named column range

Excel 2013
I am trying to use my excel sumproduct function in VBA but no luck.
I have two formulas one is without condition that work fine in VB but the other one with condition is not working. Here are the formulas
formula with no condition work fine in Excel
=SUMPRODUCT(tblProduct[Qty],tblProduct[amount])
and its VBA code that working fine in VBA excel userform
vGrndTot = Application.SumProduct(Range("tblProduct[Qty]"), Range("tblProduct[amount]"))
Conditional SUMPRODUCT working fine in excel
=SUMPRODUCT(--(tblProduct[prodID]="XYZ"),tblProduct[Qty],tblProduct[amount])
and its VBA code that i am tying to use but it not work (error type missmatch)
vTot = Application.SumProduct(--(Range("tblProduct[prodID]") = "XYZ"), Range("tblProduct[Qty]"), Range("tblProduct[amount]"))
any hint what I am doing wrong ?
I read so many question some said use evaluate (that too didn't work) some said use +0, or * 1 but i had no luck.
It took my 2 days but finally I got it with 2 key point
to evaluate the formula must appears EXACTLY SAME as in the worksheet cell including doublequotes. and to have doublequotes it need to have 4 doublequotes, strange though (see the vbDoubleQuote value below).
here is the final solution
' vProdID = coming from tblProdList one by one
vbDoubleQuote = """"
vFormula2Evalaute = "=SUMPRODUCT(--(tblProduct[prodID]=" & vbDoubleQuote & vProdID & vbDoubleQuote & ") ,tblProduct[Qty],tblProduct[UP])"
MsgBox Evaluate(vFormula2Evalaute)

Long formula works when put in cell but not when inserted from VBA

Firstly, this is a long and ugly formula warning.
What I am trying to do is to get VBA to insert this formula into Excel. If I get VBA to insert it without the '=' and then manually add it in Excel, it proves the formula works. Yet if I try to get VBA to insert and run the formula, with the '=' prefix, all in one go then I get a run-time error.
Any ideas how I can get VBA to insert and run this formula?
ActiveCell.FormulaR1C1 = _
"=IF(P1=""EQS FW"",IF(Statistics!B3=""Cadmium"",IF(AND(INDIRECT(ADDRESS(ROW(INDEX($B$3:$B$300,MATCH(""Alkalinity as CaCO3"",$B$3:$B$300,0))),9))>'Hardness-bands'!$B$5,INDIRECT(ADDRESS(ROW(INDEX($B$3:$B$300,MATCH(""Alkalinity as CaCO3"",$B$3:$B$300,0))),9))<'Hardness-bands'!$C$5),'Hardness-bands'!$D$5,IF(AND(INDIRECT(ADDRESS(ROW(INDEX($B$3:$B$300,MATCH(""Alkalinity as CaCO3"",$B$3:$B$300,0))),9))>'Hardness-bands'!$B$6,INDIRECT(ADDRESS(ROW(INDEX($B$3:$B$300,MATCH(""Alkalinity as CaCO3"",$B$3:$B$300,0))),9))<'Hardness-bands'!$C$6),'Hardness-bands'!$D$6,IF(AND(INDIRECT(ADDRESS(ROW(INDEX($B$3:$B$300,MATCH(""Alkalinity as CaCO3"",$B$3:$B$300,0))),9))>'Hardness-bands'!$B$7,INDIRECT(ADDRESS(ROW(INDEX($B$3:$B$300,MATCH(""Alkalinity as CaCO3"",$B$3:$B$300,0))),9))<'Hardness-bands'!$C$7),'Hardness-bands'!$D$7,IF(AND(INDIRECT(ADDRESS(ROW(INDEX($B$3:$B$300,MATCH(""Alkalinity as CaCO3"",$B$3:$B$300,0))),9))>'Hardness-bands'!$B$8,INDIRECT(ADDRESS(ROW(INDEX($B$3:$B$300,MATCH(""Alkalinity as CaCO3"",$B$3:$B$300,0))),9))" & _
"<'Hardness-bands'!$C$8),'Hardness-bands'!$D$8,IF(AND(INDIRECT(ADDRESS(ROW(INDEX($B$3:$B$300,MATCH(""Alkalinity as CaCO3"",$B$3:$B$300,0))),9))>'Hardness-bands'!$B$9,INDIRECT(ADDRESS(ROW(INDEX($B$3:$B$300,MATCH(""Alkalinity as CaCO3"",$B$3:$B$300,0))),9))<'Hardness-bands'!$C$9),'Hardness-bands'!$D$9,""Err""))))),IF(Statistics!B4=""Copper"",IF(AND(INDIRECT(ADDRESS(ROW(INDEX($B$3:$B$300,MATCH(""Alkalinity as CaCO3"",$B$3:$B$300,0))),9))>'Hardness-bands'!$B$13,INDIRECT(ADDRESS(ROW(INDEX($B$3:$B$300,MATCH(""Alkalinity as CaCO3"",$B$3:$B$300,0))),9))<'Hardness-bands'!$C$13),'Hardness-bands'!$D$13,IF(AND(INDIRECT(ADDRESS(ROW(INDEX($B$3:$B$300,MATCH(""Alkalinity as CaCO3"",$B$3:$B$300,0))),9))>'Hardness-bands'!$B$14,INDIRECT(ADDRESS(ROW(INDEX($B$3:$B$300,MATCH(""Alkalinity as CaCO3"",$B$3:$B$300,0))),9))<'Hardness-bands'!$C$14),'Hardness-bands'!$D$14,IF(AND(INDIRECT(ADDRESS(ROW(INDEX($B$3:$B$300,MATCH(""Alkalinity as CaCO3"",$B$3:$B$300,0))),9))>'Hardness-bands'!$B$15,INDIRECT(ADDRESS(ROW(INDEX($B$3:$B$300," & _
"MATCH(""Alkalinity as CaCO3"",$B$3:$B$300,0))),9))<'Hardness-bands'!$C$15),'Hardness-bands'!$D$15,IF(AND(INDIRECT(ADDRESS(ROW(INDEX($B$3:$B$300,MATCH(""Alkalinity as CaCO3"",$B$3:$B$300,0))),9))>'Hardness-bands'!$B$16,INDIRECT(ADDRESS(ROW(INDEX($B$3:$B$300,MATCH(""Alkalinity as CaCO3"",$B$3:$B$300,0))),9))<'Hardness-bands'!$C$16),'Hardness-bands'!$D$16,""Err"")))),IF(Statistics!B4=""Zinc"",IF(AND(INDIRECT(ADDRESS(ROW(INDEX($B$3:$B$300,MATCH(""Alkalinity as CaCO3"",$B$3:$B$300,0))),9))>'Hardness-bands'!$B$20,INDIRECT(ADDRESS(ROW(INDEX($B$3:$B$300,MATCH(""Alkalinity as CaCO3"",$B$3:$B$300,0))),9))<'Hardness-bands'!$C$20),'Hardness-bands'!$D$20,IF(AND(INDIRECT(ADDRESS(ROW(INDEX($B$3:$B$300,MATCH(""Alkalinity as CaCO3"",$B$3:$B$300,0))),9))>'Hardness-bands'!$B$21,INDIRECT(ADDRESS(ROW(INDEX($B$3:$B$300,MATCH(""Alkalinity as CaCO3"",$B$3:$B$300,0))),9))<'Hardness-bands'!$C$21),'Hardness-bands'!$D$21,IF(AND(INDIRECT(ADDRESS(ROW(INDEX($B$3:$B$300,MATCH(""Alkalinity as CaCO3"",$B$3:$B$300,0))),9))>'Hardness-ban" & _
"ds'!$B$22,INDIRECT(ADDRESS(ROW(INDEX($B$3:$B$300,MATCH(""Alkalinity as CaCO3"",$B$3:$B$300,0))),9))<'Hardness-bands'!$C$22),'Hardness-bands'!$D$22,IF(AND(INDIRECT(ADDRESS(ROW(INDEX($B$3:$B$300,MATCH(""Alkalinity as CaCO3"",$B$3:$B$300,0))),9))>'Hardness-bands'!$B$23,INDIRECT(ADDRESS(ROW(INDEX($B$3:$B$300,MATCH(""Alkalinity as CaCO3"",$B$3:$B$300,0))),9))<'Hardness-bands'!$C$23),'Hardness-bands'!$D$23,""Err"")))),Statistics!R4))),Statistics!R3)"
Wow, that is pretty big. You definitely ought to break that up a fair amount.
Anyway, I think it might be because you are trying to insert speech marks into your string. In VBA debug mode, copy the entire string and have a look at it in the immediate window. Is it exactly the same as the string when in an Excel cell? My guess would be not.
Try replacing the double speech marks:
P1=""EQS FW""
with something like this:
P1=" & """" & "EQS FW" & """"
That will insert the speech marks correctly for you.
Another thought. It will be tricky doing the speech mark adjustments, so start by trying it out on a small section of the vast formula and build it up gradually.

Writing formula into an Excel Range with Option Strict On

Is it possible to write formulas across a range in Excel from VB.Net? I'm using a String array to hold a list of formulas that I would like to apply to an Excel range, instead of looping through and writing them one at a time.
This line is what I am attempting to use to write to a range:
xlWorkSheet.Range("AF" & intCurrentRow.ToString & ":AG" & intCurrentRow.ToString).Formula = formulas
The formula is being written to Excel, but Excel is actually displaying the formula, instead of the calculated value. If I write each formula to each cell like this:
xlWorkSheet.Range("AF" & intCurrentRow.ToString).Formula = formulas(0)
xlWorkSheet.Range("AG" & intCurrentRow.ToString).Formula = formulas(1)
It works perfectly fine and Excel displays the calculated values as it should. Almost seems like I'm missing a step but I haven't been able to find anything in my research.
As soon as I hit post I figured out the problem. Instead of using the .Formula property of an Excel.Range, you have to use the .FormulaArray property instead.
xlWorkSheet.Range("AF" & intCurrentRow.ToString & ":AG" & intCurrentRow.ToString).FormulaArray = formulas

Identifying and using Relative variable in excel VBA Macro?

Alright, so I have a spreadsheet, and I want to use this code (and more) but I'm getting problems. I want to take row A and Find the [-x] I should be using (see RC[StartColumn]) and autofill the rest. I then want to be able to repeat the steps for columns A-AF.
So essentially I want to perform the first calculation below, and the second one right next to that, and I want to be able to start it anywhere on the document. I then want to be able to copy that down each row for every column leading up to the first cell I chose.
Problem is I'm incredibly new to Macros, I put that together by observing my record macro results and playing around a little, but this is becoming too advanced for my current level and I want to finish this by today if possible. Could someone please show me the way, in a way that could teach me so I could do this on my own in the future?
Sub ConcatenateStep1()
Dim StartColumn As Integer
StartColumn = 1 - ActiveCell.Column
ActiveCell.FormulaR1C1 = _
"=IF(AND(RC14=R[1]C14),IF(OR(ISNUMBER(FIND(LOWER(RC[StartColumn]),LOWER(R[1]C[StartColumn]),1)),ISNUMBER(FIND(LOWER(R[1]C[StartColumn]),LOWER(RC[StartColumn]),1))),IF(LEN(RC[StartColumn])<LEN(R[1]C[StartColumn]),R[1]C[StartColumn],RC[StartColumn]),CONCATENATE(RC[StartColumn],"", "",R[1]C[StartColumn])),IF(AND(RC14<>R[1]C14,RC14<>R[-1]C14),RC[StartColumn],"" ""))"
Range("AK2").Select
Set SourceRange = Range("AK2")
Set fillRange = Range("AK2:AK22000")
SourceRange.AutoFill Destination:=fillRange
Range("AL2").Select
ActiveCell.FormulaR1C1 = _
"=IF(AND(RC14=R[1]C14,RC14<>R[-1]C14),IF(OR(R[1]C[-1]="" "",ISNUMBER(FIND(LOWER(RC[-1]),LOWER(R[1]C[-1]),1)),ISNUMBER(FIND(LOWER(R[1]C[-1]),LOWER(RC[-1]),1))),IF(LEN(RC[-1])<LEN(R[1]C[-1]),R[1]C[-1],RC[-1]),CONCATENATE(RC[-1],"", "",R[1]C[-1])),IF(AND(RC14<>R[1]C14,RC14<>R[-1]C14),RC[-1],"" ""))"
Set SourceRange = Range("AL2")
Set fillRange = Range("AL2:AL22000")
SourceRange.AutoFill Destination:=fillRange
Range("AL2").Select
End Sub
This is only a partial answer.
Are these incredibly long and complicated formulae the best way of achieving whatever you want to achieving?
There are two errors in the first formula that prevent it being accepted by Excel when the macro attempts to place it in a cell.
The formula is a long string containing StartColumn. But StartColumn is a variable. You need to replace every occurence of StartColumn with " & StartColumn & ".
Within a string each double quote required in the result must be replaced by two double quotes. Within CONCATENATE(RC[StartColumn],"", "",R[1]C[StartColumn]) the double quotes have not been doubled although those at the end of the formula have.
Excel will accept the following (which means it is syntactically correct) although I do not understand its purpose so it may be logically incorrect:
ActiveCell.FormulaR1C1 = _
"=IF(AND(RC14=R[1]C14),IF(OR(ISNUMBER(FIND(LOWER(RC[" & StartColumn & _
"]),LOWER(R[1]C[" & StartColumn & "]),1)),ISNUMBER(FIND(LOWER(R[1]C[" & _
StartColumn & "]),LOWER(RC[" & StartColumn & "]),1))),IF(LEN(RC[" & _
StartColumn & "])<LEN(R[1]C[" & StartColumn & "]),R[1]C[" & StartColumn & _
"],RC[" & StartColumn & "]),CONCATENATE(RC[" & StartColumn & _
"],"""", """",R[1]C[" & StartColumn & _
"])),IF(AND(RC14<>R[1]C14,RC14<>R[-1]C14),RC[" & StartColumn & "],"" ""))"
If I have parsed this formula correctly, CONCATENATE(RC[StartColumn],"", "",R[1]C[StartColumn]) has the same output as CONCATENATE(RC[StartColumn],R[1]C[StartColumn])
I agree with MP24, you must clarify your question before I or someone else can help you further. The Macro Recorder records syntactically correct VBA but it is not good VBA. It does not know your objective so records individual keyboard actions when a skilled programmer would combine them. It is almost never a good idea to use Select or to work with the ActiveCell but the Macro Recorder has no choice but to do so.
Part 2
Although Excel allowed the macro to place the first forumula, it later complained the formula contains a circular reference. Its gone midnight here, I will look at it tomorrow.
Part 3
Having looked at your first formula again, I believe I incorrectly parsed it last night. I now believe the concatenate function is correct. Also it appears that the circular reference depends on the location of the ActiveCell when the macro starts. I was able to clear this error by selecting a different start position.
My current attempt to parse your formula gives:
Outer: "=IF(X1,X2,X3)"
X1: AND(RC14=R[1]C14)
X2: IF(X4,X5,X6)
X3: IF(X7,RC[StartColumn],"" "")
X4: OR(X8,X9)
X5: IF(X10,R[1]C[StartColumn],RC[StartColumn])
X6: CONCATENATE(RC[StartColumn],"", "",R[1]C[StartColumn])
X7: AND(RC14<>R[1]C14,RC14<>R[-1]C14)
X8: ISNUMBER(X11)
X9: ISNUMBER(X12)
X10: LEN(RC[StartColumn])<LEN(R[1]C[StartColumn])
X11: FIND(LOWER(RC[StartColumn]),LOWER(R[1]C[StartColumn]),1)
X12: FIND(LOWER(R[1]C[StartColumn]),LOWER(RC[StartColumn]),1)
I have used macros to place formulae so they can later give changing results as the user enters values. Do you want changing results? If not, replacing this formula with VBA would almost certainly give more understandable and more maintainable code.
I do not approve of formulae like this. I am aware that many people use complex formulae successfully and are pleased with the results. However, I have spent too much of my life picking up the pieces left by over clever people who have moved on. How long does it take to get a formula like this correct? How long does it take to amend when six or twelve months later a slightly different result is required? Too often, in my experience, the person who has to amend it six or twelve months later is not the original author. With VBA the author can leave comments saying what the code is doing but with formulae the author cannot. Over clever authors don't always leave the comments they should but at least VBA code is usually easier to decode than a complex formula.

Macro to copy and change set numbers Excel

so am working on a spreadsheet to simplify logging of data. However it's quite a tedious process of copy, paste & change. Is there a way I can create a Macro to copy the following:
=IF(Trade2!I16=99,0,Trade2!I15)
Paste it the cell directly below but as
=IF(Trade3!I16=99,0,Trade3!I15)
Beyond this it needs to be copied 100 times. Am at 15 typing it manually each time and losing the will to live haha
This seems insanely simple but everything am trying is leading to a massive mess, am good at getting the spreadsheet side working but the coding isn't my strong point.
Any advice would be greatly appreciated
If you use this formula:
=IF(INDIRECT("Trade"&ROWS(A$1:A1)&"!I16")=99,0,INDIRECT("Trade"&ROWS(A$1:A1)&"!I15"))
this returns:
=IF(Trade1!I16=99,0,Trade1!I15)
But you can now copy it down, and the sheet number increases.
The ROWS formula functions as a counter as you copy it down. The INDIRECT formula returns a reference to a sheet.
not sure what you mean but try this
Sub Main()
Dim i As Long
For i = 1 To 10000
Range("A" & i).Formula = "=IF(Trade2!I" & i + 1 & "=99, 0, Trade2!I" & i & ")"
Next i
End Sub