VBA USING TWO DIFFERENT RESULT USING countif VARIABLE - vba

Good Evening
I have a problem on VBA ​I have a variable as countif
Dim Y As Integer
Y = Application.WorksheetFunction.CountIf(Worksheets("Calc_Giac").Range("I11:EZ11"), ">0")
So If I use the variable in a formula
Range("B21").Formula = "=SumIF((I11:EZ11), "">0"") / (" & Y & ")"
The value is correct
But if use in a condition the result is the variable*-1
If ("(" & Y & ")" > 0) Then
Range("L19") = "(" & Y & ")"
Else
Range("L19") = "HELLO"
End If
Any Idea about it?

First: You have a strange if-condition. Let's assume that Y has the value 3 as a result of your CountIf: "(" & Y & ")" resolves in a String "(3)". After that, you check if the string "(3)" is greater that 0. That makes no sense. Try
If Y > 0 then
Second: You write the String "(3)" into a cell. Now depending on how the cell is formatted, either you have "(3)" (as String) in the cell (when the cell is formatted as Text), or Excel tries to convert the string "(3)" into a number. However, numbers in Excel that are entered with brackets are interpreted as negative numbers (try it by entering "(3") into a cell manually. Use:
Range("L19").Value = 3
However, within the formula, =SumIF((I11:EZ11), "">0"") / (3), the (3) is just part of the calculation and the brackets tells Excel to evaluate anything within the brackets first before continuing the calculation. As 3 is already evaluated, there is nothing to do so the brackets are ignored.

Related

Writing a formula with concatenated parts into a cell

Scenario: I have a code that should write a formula to a worksheet cells. This formula is for an API to retrieve some value. My formula is inside a loop (this is done for multiple columns) and references the first row for an identifier.
The original formula:
=FS(B1;"FI(DATE,,DATE)")
The modified formula with the floating reference (inside the loop):
For i = 1 To lColumn
If wb.Worksheets("Dates").Cells(i, 1).Value <> "" Then
wb.Worksheets("Dates").Cells(i,2).value = "=FS(" & i & "1;"FI(DATE,,DATE)")"
End If
Next i
Where lColumn is some pre-defined number.
Issue: I keep getting the "Unexpected end of statement" error in the formula part of the loop.
What I already tried: I tried different variations, repositioning the "s and 's, for example:
wb.Worksheets("Dates").Cells(i,2).value = "'"=FS(" & i & "1;"FI(DATE,,DATE)")""
or
wb.Worksheets("Dates").Cells(i,2).value = "'=FS(" & i & "1;"FI(DATE,,DATE)")"
or
wb.Worksheets("Dates").Cells(i,2).value = "'""=FS(" & i & "1;"FI(DATE,,DATE)")"
and so on. But the error still persists.
Question: What is the proper way to do this operation?
Working with formulas in VBA is a little bit tricky:
To write a formula, use the range.formula property, not the .value.
You have to write the formula as if you are using an english Excel. Parameter-separator is comma (not semicolon).
If a formula needs a quote, double it so that the VBA compiler understands that you want a quote within a string.
I find it helpfull to write a formula into a variable before assigning it - you can check in the debugger if it is exactly how it should before assigning it.
To check how the formula should look like, write it into a cell, change to the VBA-editor, open the immediate window and write ? activecell.formula
Try (untested as the formula you need is not valid to us):
with wb.Worksheets("Dates")
dim f as string, adr as string
adr = cells(i, 1).address(false, false) ' get rid of Dollar signs
f = "=FS(" & adr & ",""FI(DATE,,DATE)"")"
.Cells(i, 2).formula = f
end with
wb.Worksheets("Dates").Cells(i,2).formula = "=FS(" & Cells(1, i).Address(0,0) & ";""FI(DATE,,DATE)"")"
There may be a better way to convert the column number to a letter (which is the problem you are having, along with the double quotes)!

Changing a cell formula based on for loop iteration

I am trying to insert and change a counta formula based on the iteration of the for loop. The problem I am facing is that even though the code runs without error, nothing happens. The totalrow variable is consistently 0. I'm not sure where I am going wrong here. All the variable have been initialized outside the loop. CurrentColname is string, countUsedCols is long, totalRows is long.
For i = 2 To countUsedCols
ActiveSheet.Cells(3, i).Select
currentColName = ActiveSheet.Cells(3, i).Value
If currentColName = "Valid From" Then
totalrow = ActiveWorkbook.Sheets("Customer_Facing_View").Range("AR1").Formula = "=COUNTA($" & i & ":$" & i & ")"
totalrow = ActiveWorkbook.Sheets("Customer_Facing_View").Range("AR1").Value
A couple of things.
In vba when you put X=Y=Z X becomes a Boolean value based on whether y = z or not.
So when you write:
totalrow = ActiveWorkbook.Sheets("Customer_Facing_View").Range("AR1").Formula = "=COUNTA($" & i & ":$" & i & ")"
Totalrow is returning false because the formula in that cell is not the same as the string you have provided.
Second your COUNT A will resolve to a row not a column. i is a number and not a letter.
So remove the totalrow = from the first expression and change the range reference.
ActiveWorkbook.Sheets("Customer_Facing_View").Range("AR1").Formula = "=COUNTA(" & Columns(i).Address &")"
I guess you would like to write a formula into Cell AR1 to calculate the number of rows (with the first totalrow statement); and get that value back (with the second totalrow statement). But I believe the first totalrow statement is wrong as Scott indicated. You need change it.
Also for the Counta formula you need to include your original worksheet name otherwise it just count the column in the Customer_Facing_View worksheet.

Variable number of terms in an Excel VBA Formula?

Is it possible to write a formula in VBA for excel such that there are "n" terms in the formula, with the number of terms changing as the value of "n" does?
For instance, say you wanted to code cell a1 such that it was the sum of a2 and a3. Then you wanted b1 to be the sum of b2,b3,b4,b5 and so on such that each column 1 row 1 cell for a range of cells is the sum of "n" cells below it where "n" varies from column to column. Say that all cell addresses you wanted to use are known and stored in an array.
Here is some code to better explain what I'm asking:
For i = 0 to n
Range(arr1(i)).formula = "=" & range(arr2(i)).value & "-(" _
& Range(arrk(i)).value & "+" & Range(arrk+1(i)).value & "+" _
& Range(arrk+2(i)).value & "+" & ... & ")"
Next i
So what I'm looking for is one piece of VBA code that can make a cell formula contain a dynamic number of terms. The code above would make cell a1's value = a-(b+c+d+...) where the number of terms in the bracket is variable, depending on which cell the formula is applied to.
The image here shows an example of what I want to do. I'd like some code which could take "years income" and subtract a variable amount of "expenses" from it, where the number of expenses varies each year (but the number stays fixed for that year). The code needs to use a formula so that the expenses entries can be modified by the user.
Have you tried Array Formula ? :
Array Formula :
An Excel Array Formula performs multiple calculations on one or more sets of values (the 'array arguments') and returns one or more results.
details : http://www.excelfunctions.net/Excel-Array-Formulas.html
Thanks for the suggestions everyone, I found a solution (not a particularly efficient one, but a solution nonetheless) to the conundrum today.
First I created an array which used the "pattern" of the Junk cells to list every cell address which was to be included.
Taking this array, I used a for loop to create a series of temporary arrays with the application.index command. For each temporary array, I used the Join command to turn the list of cells into a single string which I then inputted into a cell formula. Thanks to #thepiyush13 whose array.formula approach inspired this.
Here's some example code to show what I did:
' hypothetical array containing two sets of cells to use
Dim array1(0 To 1, 0 To 1) As Variant
Dim vartemp As Variant
Dim vartemptransposed As Variant
' col 1 will be used to add I10 and I13, col2 I11 and I14
array1(0, 0) = "$I$10"
array1(1, 0) = "$I$13"
array1(0, 1) = "$I$11"
array1(1, 1) = "$I$14"
For i = 1 to 2
'application.index(arr,row#,col#) to create a new array
vartemp = Application.Index(array1, 0, i)
'error if not transposed
vartemptransposed = Application.Transpose(vartemp)
randomstring = Join(vartemptransposed, ",")
totalvalue = 100
'example formula: a1 = totalvalue - sum(I10,I13). a2 = totalvalue - sum(I11,I14)
Cells(1,i).formula = "=" & totalvalue & "-SUM(" & randomstring & ")"
Next i
I needed the code to run this many many times on large lists which are generated dynamically but always hold the same pattern of where the "junk cells" are. Not included in the code, but I also used another array for the cell addresses of where to place the formula.

Looping through a range of rows using a string

I am trying to create a macro that will enter ranges within a chart's data labels via the "Label Contains: Value From Cells" option. Each label corresponds to a row within a sheet such as =Breakdown!$B$27:$K$27. I recorded a macro to find the language for this action and it came back as:
ActiveChart.SeriesCollection(i).DataLabels.Format.TextFrame2.TextRange. _
InsertChartField msoChartFieldRange, "=Breakdown!$B$27:$K$27", 0
I can loop through the SeriesCollection by "Dim i As Integer". Is there any way I can set =Breakdown!$B$27:$K$27 as a string or something with variables for the cell numbers so that I can cycle through the rows?
Using string concatenate operator & and CStr function which converts an expression into a string, it'll work out well.
"=Breakdown!$B$" & CStr(i) & ":$K$" & CStr(i)

Pad single-digit numbers with a zero

I have a loop like this to save sheets as CSV files but my first 9 sheets are name liked sinani-01 ... sinani-09 (not like sinani-1 ... sinani-9). How I can concatenate a 0 only before numbers less than 10?
Sub Adder()
Dim animal As String
Dim i As Integer
For i = 1 To 120
animal = "sinani-" & i
Sheets(animal).SaveAs "E:\Data\CSV\" & animal & ".csv", xlCSV
Next i
End Sub
VBA has a Format() function that you can use to pad numbers.
animal = "sinani-" & Format$(i, "00")
This will pad single-digit numbers with a 0. Your two- and three-digit numbers will continue to work as expected.
In the fifth line use the Format function like this:
animal = "sinani-" & Format(i, "#00")
The # means optionally a digit (i.e. present only if there are that many digits in i), 0 means definitely a digit, whereby leading zeros are used if i hasn't got enough digits.
Concatenate with a leading series of zeroes and peel off as many digits from the right-hand side as you need.
animal = "sinani-" & Right("00" & i, 2)
'alternate for many leading zeroes (e.g. DUNS number)
animal = "sinani-" & Right(String(9, "0") & i, 9)
Replace & i by & IIF(i < 10,"0","") & i
On edit: Even though in this case Format provides a cleaner solution than IIF, the IIF trick has some other uses in tweaking output. For example, if you wanted to inform the user how many cells were found which satisfy some condition you could use something like
MsgBox n & "cell" & IIF(n <> 1,"s","") & " found"
to gracefully handle plural vs. singular endings