the curious case of disappearing decimals - vba

I have an issue with disappearing decimal places when I put them into arrays and then pasting them out again. not sure why this is happening at all. any soluntions?
an example below:
excel:
A B
1 Input $213,213,132,135,654.00 <--format: Accounting
2 =B1/1000000 $213,213,132.14 <--format: Accounting
3 output $213,213,132,135,700.00 <--format: Accounting
Code:
Sub test()
Dim ar() As Variant
ReDim ar(1)
ar(1) = Cells(2, 2).Value
ar(1) = ar(1) * 1000000
Cells(3, 2) = ar(1)
End Sub

213213132135654.00 / 1000000 = 213213132.135654
You provided the answer when you mentioned that it only does it when formatted as accountancy. Accountancy works to four decimal places only making the result 213213132.1357, when when multiplied gets to the non-matching 213213132135700.00.
As to a fix, I would suggest either using rounding to 4 decimal places in all formula or do the math in another worksheet as numbers and then present the results on your main worksheet as accountancy.

Related

Trying to create a macro to perform 100 iterations and paste resulting values (2 adjacent row cells) to a 2 x 100 array

I have a worksheet that uses randomly generated numbers in calculations to produce results in two adjacent cells (let's say A1 and A2). I am trying to perform 100 iterations where I'm simply "Calculating Formulas" on the worksheet and then trying to store the results of each iteration next to A1 and A2 (so iteration 1 would be in B1 and B2 and iteration 100 would be in CW1 and CW2). Thanks in advance for your help. Using Excel 2010 if that matters.
Dim Iteration As Integer, i As Integer
Dim val As Variant
Iteration = 100
For i = 1 To Iteration
Calculate
Range("A1:A2").Select
Selection.Copy
Range("B" & Rows.Count).End(x1Up).Offset(0, 1).PasteSpecial
Paste:=xlPasteValues
Next i
End Sub
I think your major problem was with the location you were selecting for the destination address - you were finding the last unused cell in column B, then shifting over one column (i.e. to column C) and pasting the first set of results. Then you were using that same location for the second set of results, etc.
Sub Test()
Dim Iteration As Integer, i As Integer
Dim val As Variant
Iteration = 100
'Use a "With" block so that it can be easily changed in the future
'to refer to a specific sheet if needed
With ActiveSheet
For i = 1 To Iteration
Calculate
'Determine the last used column on row 1,
' offset 1 column to the right,
' resize to refer to 2 rows,
' set values to the values in A1:A2
.Cells(1, .Columns.Count).End(xlToLeft).Offset(0, 1).Resize(2, 1).Value = .Range("A1:A2").Value
Next i
End With
End Sub
As pointed out by Steve Lovell, you also had a typo in your original code. It is a good habit to include Option Explicit as the first line in every code module. That will force you to declare all the variables that you use, and the compiler would have highlighted x1Up and given a "Variable not defined" error.

excel vba input reference cell into formula and loop

I have what I thought was a very basic VBA challenge, and have spent hours searching for an answer. Thanks if someone can point me to the right place if already addressed.
I have a formula that is B1 + C1 = D1, and have two 1x5 matrix of data inputs, one for cell B1 and one for cell C1, say [1,2,3,4,5] and [A,B,C,D,E], respectively, in cells (B2:B7) and (C2:C7). I would like to loop through the inputs, such that I get five unique answers [1+A, 2+B, 3+C, 4+D, 5+E], and output those answers in an adjacent 1x5 matrix, say in cells (D2:D7).
Recording a macro does not work here, as it records a copy/paste action that is inflexible for future use (for expanded matrices, other sheet locations, more complex formulas, etc).
Any help much appreciated.
Henry
UPDATE: I believe I need to be using "Do While" or some similar loop code, and additional "For" and "Next" coding.
UPDATE: Here is a step-by-step picture of what I am trying to do with the code:
step-by-step process results image
Here's the solution code:
Sub IterationMacro()
'Declare Variables
Dim h, i, j, k As Integer
Dim mySheet As Worksheet
Dim myAnswer As String
'Set Worksheet
Set mySheet = ActiveSheet
'Set # of Iterations
h = Range("B2").Value
'Clear Previous Contents
Range("C4:D4").ClearContents
Range("e5:e11").ClearContents
'Run Through Loops
For i = 5 To h + 4
For j = 3 To 4
mySheet.Cells(4, j).Value = mySheet.Cells(i, j).Value
Next
'Calculate Workbook
Calculate
mySheet.Cells(i, 5).Value = mySheet.Cells(4, 5).Value
Next
End Sub
If you could draw a table or something to use as an example, it might help.
Assuming I'm undersatnding you, you want to use a formula in D1, and fill down to D7, resulting in showing B+C=D in each row:
Range("D1").Formula="=B1+C1"
Range("D1:D7").Filldown
Edit:
Having been given the example image, it looks like you want math to happen in Row 2 (headers in Row 1). In Row 2 you want to pull up values from Row "i" and add them in Row 2, then paste the answer of that sum in Row "i".
Dim i as Integer 'i is the variable for the loop
For i = 3 to 9 'based on the picture, 3 to 9 are the 1 through 7 values
Cells(2,1).Value=Cells(i,1).Value 'pulls up Column A value from the loop to Row 2
Cells(2,2).Value=Cells(i,2).Value 'pulls up Column B value from the loop to Row 2
Cells(2,3).Formula="=A2+B2" 'Sums A2 and B2 into C2
Cells(2,3).Copy Cells(i,3) 'Copies the summed value to Row "i" in Column C
Next i 'Moves to next "i" in the loop
Let me know if that is more to your point.
Edit:
With dynamic ranges, you still know your starting point. You would look at something similar to:
Dim i as Integer
Dim LR as Long
Dim LC as Long
LR=Cells(Rows.Count,"A").End(xlUp).Row
LC=Cells(1,Columns.Count).End(xlToLeft).Column
For i = 3 to LR 'Still starting at 3, because of the example
Cells(2,1).Value=Cells(i,1).Value
Cells(2,2).Value=Cells(i,2).Value
Cells(2,LC+1).Formula="=A2+B2" 'Note the LC+1 goes one row BEYOND the last column
Cells(2,3).Copy Cells(i,LC+1)
Next i
In the last example, you can see syntax for dynamic ranges. Note that LR and LC are defined outside of the loop and do not change for the duration of the subroutine.

Excel VBA dividing 2 by 60

Have you ever noticed a problem dividing 2 / 60 in Excel Vba code? I am using Excel 2013. Please test the code below:
Sub test1()
Dim A As Integer
Dim B As Integer
MsgBox 2 / 60
A = 2
B = 60
MsgBox A / B
End Sub
Sub test2()
Cells(1, "a") = 2
Cells(1, "b") = 60
Cells(1, "c") = Cells(1, "a") / Cells(1, "b")
MsgBox Cells(1, "a") / Cells(1, "b")
End Sub
Test1 will generate a wrong answer for the math operation. Result should be 0,0333333, but it brings 3,3333333E-02. Test2 works with cells and it brings correct result.
What is wrong with my code? Is it a bug? I am soooo intrigued, why can't vba do the right calculation?
Thanks for the help
In number part E+XX or E-XX, XX denotes how many digits the decimal point is shifted right or left.
So in your 3.333333E-02 shift the decimal point 2 places left and you get 0.03333333
One of the points of such a notation is to spare you from zeros (0.0000012345 = 1.2345E-06) and to correctly show you only digits which are within the number precision (hypthetical 1234567890123456789 = 1.2345678E+18 (rest of digits is 'clipped').
And 5E+00 = 5 :) no shift.
More information: E notation

Inside a loop, how to indicate "all rows" when taking the mean of multiple columns (Visual Basic)

I have a loop wherein I take the mean of several columns of numbers with the same number of rows each.
The point of the loop is to capture these means in a new vector.
So for each loop I need to indicate "all rows". In matlab this would be easy, just use ":" But I can't figure out what the analogy is in VB. Please help! Thanks.
(Please advise me as to what I put in the code below where I have ALLROWS).
My attempt so far:
For i = 1 To CA
mrCA11(i) = Application.WorksheetFunction.Average(revCA11(**ALLROWS**,i))
Next i
In matlab this would be:
For i = 1:CA
mrCA11(i) = mean(revCA11(:,i));
Next i
EDIT: I've also tried this trick to no avail:
For j = 1 To CA
For i = 1 To s11
temp11(i) = revCA11(i, j)
Next i
mrCA11(j) = Application.WorksheetFunction.Average(temp11)
Next j
I get the error message: "Unable to get the Average property of the Worksheet Function class"
As everybody (Tim and shahkalpesh at least) pointed out, we need to understand what is revCall or more specifically, we need to understand how you want to give them ALL ROWS in argument.
Finding the last row (or column or cell)
A common Excel issue is to find the last used row / column / cell.
This will give you the end of your vector.
Excel give you several methods to deal with this:
xlTypeLastCell
Last cell used in the entire sheet (regardless if it's used in column A or not)
lastRow = ActiveSheet.Cells.SpecialCells(xlCellTypeLastCell).Row
End(xlUp)
Last cell used (including blanks in-between) in Column A is as simple as this:
lastRow = Range("A" & Rows.Count).End(xlUp).Row
End(xlToLeft)
Last cell used (including blanks in-between) in Row 1 is as simple as this:
lastRow = ActiveSheet.Cells(1, Columns.Count).End(xlToLeft).Row
UsedRange
Last cell used in the WorkSheet (according to Excel interpretation):
Set rangeLastCell = ActiveSheet.UsedRange
Using an array as argument
The methods above told you how to find the last row (if this is what you need). You can then easily create your vector and use it in your procedure revCA11.
You can either give an array as argument as Tim pointed out in his answer with this kind of statement:
myArray = ActiveSheet.Range("A1", Cells(lastRow, lastColumn).Value
Or you can use the integer (or long) to build your vector inside your procedure as simple as declaring a range:
Range("A1:A" & lastRow)
You might clarify exactly how revCA11 is declared/created, but maybe something along these lines might work for you:
Sub Tester()
Dim arr, x
arr = ActiveSheet.Range("A1:D5").Value '2-D array
'average each column
Debug.Print "Columns:"
For x = 1 To UBound(arr, 2)
Debug.Print x, Application.Average(Application.Index(arr, 0, x))
Next x
'average each row
Debug.Print "Rows:"
For x = 1 To UBound(arr, 1)
Debug.Print x, Application.Average(Application.Index(arr, x, 0))
Next x
End Sub

VBA/excel-VBA - add two values with dot separator

I'm new to VBA and need to add two values using VBA in Excel. I receive imported values with dot-separator and if I try to add them, the dot is ignored.
So:
1.12
1.34
should result in 2.46, but I'm getting 246
Code:
Do Until (Cells(iRow, 1) = 100)
addValue = Cells(iRow, 2).Value
dValue = dValue + addValue
iRow = iRow + 1
MsgBox (dValue)
Loop
Thanks for some 101-tips...
Here is the updated code:
Dim iRow As Integer
Dim addValue As Double
Dim dValue As Double
iRow = 2
Do Until (Cells(iRow, 1) = 100)
addValue = Cells(iRow, 8)
Debug.Print "Row"; iRow; " is "; addValue
modValue = Replace(addValue, ".", ",")
MsgBox (addValue)
newVal = Cells(iRow, 8).Value
dValue = dValue + newVal
iRow = iRow + 1
Loop
MsgBox (dValue)
Basically I have a lit of values like this:
100 header
200 1.12
200 1.34
200 1.54
100 header
...
I want to sum the 200 correspondig values 1.12, 1.34, 1.54. The values show up as 112, 134 and 154.
Thanks
Would you place this line after addValue =, please?
Debug.Print "Row"; iRow; " is "; addValue
Offhand, I am suspecting that the 1.12 is not really a double.
Also, did you declare your variables? Nothing fancy, but something like
Dim iRow As Integer
Dim addValue As Double
Dim dValue As Double
Finally, you may want to consider placing the MsgBox after the loop, instead of having it give a subtotal on every; iteration.
I think you have some funny number formatting applied to the values in Excel. Highlight the range and hit Ctrl-Shift-` (or format the cells as "General" from the format menu). I bet those numbers are actually 112 and 134.
Right... The problem is formatting, and Excel's insistence on describing (say) '4/7' as 'Fourth of July' rather than four-sevenths*. Or indeed, as a textual 'Four-slash-seven'.
I do not know what strange format has been picked up in those 'decimal' cells, but you have two jobs to do:
Change the number format of those cells to 'general' so you can see
what's actually in them, rather than whatever Excel wants to
present;
Change your code to use the 'Value2' property of a range, which
gives you the raw data instead of a formatted interpretation of the
'value' - newVal = Cells(iRow, 8).Value2
I would also recommend that you declare NewVal as Double. This will coerce a type conversion to floating-point number, a far better idea than letting a 'variant' decide what type it would like to be, based on formatting information in a range.
I'd better warn you that task (1) works about half the time on data imported from Oracle databases, and numbers copied from spreadsheets originating France (where the comma is used as a decimal point) are better-suited to the semiotic analyses developed by French Deconstructivist philosophers, rather than statistical analysis and arithmetic calculation.
*You'll be able (or unable) to reproduce this error some of the time, depending on your machine locale. And that's today's big lesson: a problem is worsened when it is intermittent, unpredictable, or inconsistently-reproducible.