I'm getting a "Run-time error code '6': Overflow" message on something that is trivial (imo).
Strange problem I'm experiencing here with the code below:
Sub StageSetup()
Dim rLastDataRow As Range
Dim lCount As Long: lCount = 0
Dim lDelta As Long: lDelta = 0
1 With Worksheets("Analyzer")
2 Set rLastDataRow = .Range("A2").End(xlDown)
3 lCount = (rLastDataRow.Row - 2) / 10
4 lDelta = (rLastDataRow.Row - 2)
5 lCount = lDelta / 10
6 End With
End Sub
In debug mode, the problem is occurring on line 5 above which is odd in that it is a simple long division.
Note:
I added line 3 above after the fact just to see what happens when it is done in a single line. That works, but I'd like it to work in the form shown in line 5 as the future mods to this code will involve addition accumulations made to lCount before the division occurs.
rLastDataRow.Row when this happened was 2510 in value which so happen to be an evenly divisible value by 10 (stating the obvious).*
I could use a loop to simulate the division, but what's the point in doing that when a simple divide should suffice.
As can be seen, both lCount and lDelta are of Long type. So, this should have been trivial as there shouldn't be any form of type conversion going on here.
I've tried casting the variable and literal utilizing CLng and also the & (as I've seen in some of the threads but thought that was only meant for non-decimal base representations) in various combinations to no avail. I've also did some casting on line 4 with no effect.
Does anyone have any clue what may be going on here?
Related
I ran in a problem with an inadequate type declaration for the counter variable of a for-next loop.
What´s wrong with this code snippet?
For n As Byte = 16 to 2 Step -1
Debug.Print(n)
Next
-> The loop is never entered,
while the code
For n As SByte = 16 to 2 Step -1
Debug.Print(n)
Next
works as expected.
I´ve been using VB since 1994, currently Visual Studio Community 2019, V16.8.2, but never ran into this problem.
If n needs to be of a "signed" datatype when Step is of type SByte, Integer ..., to handle neg. numbers, why do I not get an Error, Alert ... from the VS-Compiler?
There is also not hint within the MS doc.
Sure this "problem" can be avoided by using (signed)Byte, Integer, double or decimal as datatypes, but I´d like to understand why VS doesn´t give any alert.
Did I miss something?
Regards
Werner
The Error States:
Run-time error '94'
Invalid use of Null
Options to: (End) (Debug) (Help)
I hit Debug
Microsoft Visual Basic for Applications opens window for
(Calculate Functions Code)
(Issue Below)
'Add Leap Year determination
Dim blnIsLeapYear As Boolean
Dim intYear As Integer
blnIsLeapYear = False
intYear = YY
If (intYear Mod 4 = 0) Then
blnIsLeapYear = True
If (intYear Mod 100 = 0) Then
If (intYear Mod 400 <> 0) Then
blnIsLeapYear = False
IntYear = YY is highlighted in YELLOW. I have no idea how to fix the issue.
You are missing the "End if" in your code.
Remember the if structure is:
If something then
Do what you need
End if.
for example:
If (intYear Mod 4 = 0) Then
blnIsLeapYear = True
End if
Another problem is that you are assigning the YY to intYear in intYear = YY , but you never created of populated the YY.
It is very important to put
Option Explicit at the top of each module.
This is flag whenever you use a variable which hasn't been declared.
Like you've done, it's a good idea to have at least one capital letter in every variable.
That way, when you enter line, you'll know immediately if you've spell each variable correctly as soon as you leave that line.
I always name globals in all capitals - like Public Dim YEARPAST as Long
or Const YEARPAST as Long = 1
Then I know something is a global
I know a lot of coders think globals are a bad idea but they work for me, either at the project level, or in a particular module so I don't have to pass values in variables all the time. Also, a nice way to communicate information across the project or procedures in a module.
I began toying with project euler.
I have completed problem #3, but I was only able to complete it by setting my endNumber to 71 * 486847 (manually calculated). When trying to set endNumber = 600851475143 I receive the overflow error.
I even set endNumber as Long, and even Double which I think should be plenty of digits to calculate.
I can't post the whole code here, so I'll post half in hopes someone can show me how to edit it in order to process larger numbers.
Also I noticed that "#" pops up when my code has a very large number like below.
endNumber = 600851475143#
countFactor = 0
For i = 2 To endNumber
If endNumber Mod i = 0 Then
The overflow isn't due to assigning the number 600851475143 to the Double variable it is that the Mod function does not seem to handle numbers longer than Long very well (in fact seemingly not at all).
An alternative can be to use the manual calc for Mod:
endNumber = 600851475143#
countFactor = 0
For i = 2 To endNumber
If endNumber - (Int(endNumber / i) * i) = 0 Then
If you are going to use Mod for large numbers on a regular basis then Chip Pearson's function would be a useful one (which is where I learnt about this subject matter in the first place). It is posted as a problem in Excel but works perfectly in Access.
The highest possible number to work with in a long is: 2.147.483.647
A Double is for decimal purposes, so thats not what you are looking for.
The # that pops up is because a number is to large to be shown inside that cell.
Also I don't know what you want to do with that loop. But that one is going to take a very long while to run.
on this link you can find about handling large numbers: Large Number Arithmetic
Hope that helps
I'm trying to delete the empty series from a chart in Excel 2003 using VBA. I've seen that others have had this issue in the past and I have tried all methods mentioned in their posts but have been unable to find anything that works consistently.
The chart has 14 series in it and anywhere between 3 or 9 of them can be empty. The empty ones are always between Series 4 - 12.
I've tried a few variations of code but this is primarily it:
Sheets("chart-1").Select
ActiveChart.PlotArea.Select
For i = 12 To 4 Step -1
Dim theSeries As Series
MsgBox (ActiveChart.SeriesCollection(i).Name)
Set theSeries = ActiveChart.SeriesCollection(i)
MsgBox (theSeries.Name)
theSeries.Delete
Next
I can run it successfully once for a chart, but all subsequent cycles fail with a Unable to get the Name property of the Series class error. It fails on the call to .Name.
I been able to get it work by inserting integers directly, but it will only run once for all integers except 1. It run it multiple times for Series(1).
For instance if I simply call: ActiveChart.SeriesCollection(1).Delete, then the series is deleted, but if I then run it with another integer (4, 9, 12) it won't run. It will work again for 1, but only 1. It will also work once with other integers (say 4), but all subsequent calls will fail even if I change the integer to 1 or keep it as 4, or change it to some other number.
The behaviour is really quite strange.
Any ideas would be greatly appreciated. I can't simply call ActiveChart.SeriesCollection(1).Delete repeatedly because the first 3 series are always non-empty.
Thanks.
** Update **
I just ran a test manually executing the following:
Sheets("ch-v2-12mth").Select
ActiveChart.PlotArea.Select
MsgBox (ActiveChart.SeriesCollection(1).Name)
I cycled through the SeriesCollection trying the numbers 1 - 16 (there are only 14 Series in the chart) to see the result.
1 - 3 worked fine
4 - 13 errored with Unable to get the Name property of the Series class
14 worked fine
15 - 16 errored with Method 'SeriesCollection' of object '_Chart' failed <- not surprising given the number of series in the chart.
This type of behaviour makes me think that there is a bug with Excel. Any other ideas?
There are bugs in Excel when you delete all the series from a chart. My workaround is to always leave at least one series (even if it has no data in it) in the chart. That seems to work for me.
Just thought of another thing. When you delete a series, the indexes of all the remaining series get reduced by one, so you can't delete them by looping from 1 to the number of series. What you can do instead is have a do loop that deletes them until the SeriesCollection.Count = 0 (or 1, see my comments earlier). Or a for loop that iterates backwards and always deletes the last series (i.e. SeriesCollection(SeriesCollection.Count).Delete
You cannot remove all series or the chart will remove itself. what I do to work around this is to rename all exisiting series; then enter your code to build new stuff; then run another snippet to remove the series you renamed
'rename existing series
With ActiveChart
DoEvents
For i = .FullSeriesCollection.Count To 1 Step -1
.FullSeriesCollection(i).Name = "remove" & i
Next i
End With
'your code here to build new charts
'last piece of code to remove the earlier series marked for deletion
With ActiveChart
DoEvents
For c = .SeriesCollection.Count To 1 Step -1
If .SeriesCollection(c).Name Like "*Series*" Then .SeriesCollection(c).Delete
Next c
End With
'also, you need to step backwards because each time you remove a series it will re-index
You can simplify your code to this:
Sheets("chart-1").Select
For i = 12 To 4 Step -1
MsgBox "Series " & i & ": """ ActiveChart.SeriesCollection(i).Name & """"
ActiveChart.SeriesCollection(i).Delete
Next
I don't know why the code was not working for you, but simpler is usually better. And you don't need to know the series name to delete a series.
I am trying to generate a bunch of random permutations via the the following algorithm through vba:
Function RandNumber(Bottom As Integer, Top As Integer, _
Amount As Integer) As Integer()
Dim iArr As Variant
Dim i As Integer
Dim r As Integer
Dim temp As Integer
Dim bridge() As Integer
'Application.Volatile
ReDim iArr(Bottom To Top)
For i = Bottom To Top
iArr(i) = i
Next i
Randomize
For i = Top To Bottom + 1 Step -1
r = Int(Rnd() * (i - Bottom + 1)) + Bottom
temp = iArr(r)
iArr(r) = iArr(i)
iArr(i) = temp
Next i
ReDim Preserve bridge(1 To Amount)
For i = Bottom To Bottom + Amount - 1
bridge(i - Bottom + 1) = iArr(i)
Next i
RandNumber = bridge
End Function
What RandNumber essentially does is that it randomly gives a permutation based on the bottom and top values provided by the user. Example RandNumber(1,2,1) will either be 1 or 2 randomly.
Now I am testing this function through the following routine
Sub RandNos()
Dim z() As Variant
ReDim Preserve z(1 To 2560)
For i = 1 To 2560
z(i) = RandNumber(1, 2, 1)
Next i
For i = 1 To 2560
ThisWorkbook.Sheets("Sheet2").Range("A1").Offset(i - 1, 0) = z(i)
Next i
End Sub
To my utter amazement the 'random' numbers are repeating exactly after 256 runs! (Ok, the value 2560 for i above is not exactly a co-incidence. I was suspecting that there is some pattern going on around 256 rows and thus took i as 2560)
Moreover, when I test the above function with slightly modified subroutine:
Sub RandNos2()
For i = 1 To 2560
ActiveSheet.Range("A1").Offset((i - 1) Mod 256 + 1, Int((i - 1) / 256)) = RandNumber(1, 2, 1)
Next i
End Sub
the pattern is gone. (At least the pattern of repeating after 256 values is gone. Not sure if another pattern emerges).
Now based on my knowledge the Randomize is supposed to control the randomness by generating appropriate seeds and Randomize in vba takes the seed from the timer. So my hypothesis is that in the 1st RandNos() subroutine the updates happen so quickly that the seeds don't get updated fast enough. The fact that pattern is gone when I test with the second subroutine, since in the second routine excel takes longer to write the code in the worksheet and hence the gives the code some chance to update the timer and with it the seed of the Random numbers - supports my hypothesis.
So my question here is
Is my hypothesis correct.
Should I still hope to generate a 'random' pattern in Excel VBA.
Am I making a wrong use of Randomize here
Thanks in advance for your suggestions on the issue.
EDIT: One of the suggestions in the comment was that we should call Randomize only once. I tried doing that and it seems to work. However, I would still like to know what goes wrong using Randomize as above.
in answer to your edit, your hypothesis is correct.
Randomize takes the time and generates a seed. A seed is just a starting point for Rnd.
However, note that Randomize is not one-to-one which means that for any given input into Randomize (i.e. the time) it doesn't generate the same seed every time. You appear to have discovered that Randomize has a sequence of 256 seeds for every given input. Therefore, you get a repeating sequence of 256 numbers which were supposed to be random but which clearly are not.
Reference: The VBA help page for Randomize and CS classes
You should call Randomize once only. If RandNos() is called more than once, use Randomize in the method that calls RandNos().
just for future reference to anyone else who encounters this problem, I decided to just try "slowing down" the subroutine enough to allow the system timer to reset. Application.wait did not work well, but I found that by including a simple debug.print line above the randomize call, it slowed the execution down just enough to get it to not repeat every 256. This not dramatically increase the overall run time of the subroutine. Just a thought for folks who would not mind sacrificing a little bit of optimization for a very simple fix on the pseudo-randomness.