Only Show Full X-Axis Intervals VB.NET - vb.net

I'm using the .NET charting library to show a line graph (voltage versus time). The full data length always varies (can be between 10ms of data up to ~250ms of data).
The issue I'm running into is that the final interval on the chart is usually cut short. For example if there is 230ms of data, and the chart has 50ms intervals, the final interval will be cut off after 30ms and won't show the complete interval on the x-axis. Ideally I want it to go all the way to 250ms and simply stop showing the data after 230ms (but extend the x-axis range to fully complete the interval).
Is there an option somewhere to not cut intervals short if the data ends? I haven't been able to find anything.

Just set the min and max explicitly
' make a test series, add points
Dim s As New Series()
For i = 0 To 230
s.Points.Add(New DataPoint(i, i))
Next
' add series to chart
Chart1.Series.Add(s)
' set axis interval, min, and max
Chart1.ChartAreas(0).AxisX.Interval = 50
Chart1.ChartAreas(0).AxisX.Minimum = 0
Chart1.ChartAreas(0).AxisX.Maximum = 250
If you don't want to hard-code it, it can be done programatically
Chart1.ChartAreas(0).AxisX.Maximum = Math.Ceiling(maxValue / interval) * interval
If you don't want to set the interval, you can calculate it based on the max value. This is an example but you may want to tweak the ranges and values
Private Function getInterval(maxValue As Double) As Double
Select Case maxValue
Case 0 To 10
Return 1
Case 10 To 50
Return 5
Case 50 To 100
Return 10
Case 100 To 1000
Return 50
Case Else
Return 100
End Select
End Function
'''
Dim maxValue = 33
' make a test series, add points
Dim s As New Series()
For i = 1 To maxValue
s.Points.Add(New DataPoint(i, i))
Next
' add series to chart
Chart1.Series.Add(s)
Dim interval = getInterval(maxValue)
Chart1.ChartAreas(0).AxisX.Minimum = 0
Chart1.ChartAreas(0).AxisX.Maximum = Math.Ceiling(maxValue / interval) * interval

Related

Extract two numbers from string using formula

I have formula to extract numbers from Google XML response, that can be:
9 часов 24 минут
10 h 0 min
9 h 20 min
11 h 13 min
10 Std 55 min
9 timmar 5 min
19 min
Here is current formula (value is in BZ1):
=IFERROR(IF(VALUE(IF(FIND("min";BZ1;1)=11;MID(BZ1;FIND("min";BZ1;1)-2;1);MID(BZ1;FIND("min";BZ1;1)-3;2)))<30; VALUE(LEFT(BZ1;FIND("h";BZ1;1)-2))&","&5;VALUE(LEFT(BZ1;FIND("h";BZ1;1)-2))+1);"")
Formula rounds hours and minutes to hours, for example
1 h 39 min -> 2
10 h 12 min -> 10,5
9 h 20 min -> 9,5
There is a problem that it is not able to take in consideration language changes for hours and min.
Is there any possibility to make it work so that it will:
If there is only number (case 19 min) -> extract number
If there are two numbers (case 1 h 39 min) -> extract first number as hours, then from last two spaces number as minutes
EDIT:
Check how many numbers in cell (target in CA25):
SUM(LEN(CA25)-LEN(SUBSTITUTE(CA25;{1;2;3;4;5;6;7;8;9};)))>1
If more than 1
LEFT(CA25;(FIND(" ";CA25;1)-1))&TRIM(MID(SUBSTITUTE(CA25;" ";REPT(" ";50));100;50))
If less than 1
LEFT(CA25;SUM(LEN(CA25)-LEN(SUBSTITUTE(CA25;{"0";"1";"2";"3";"4";"5";"6";"7";"8";"9"};""))))
All together
=IF(SUM(LEN(CA25)-LEN(SUBSTITUTE(CA25;{1;2;3;4;5;6;7;8;9};)))>1;LEFT(CA25;(FIND(" ";CA25;1)-1))&TRIM(MID(SUBSTITUTE(CA25;" ";REPT(" ";50));100;50));LEFT(CA25;SUM(LEN(CA25)-LEN(SUBSTITUTE(CA25;{"0";"1";"2";"3";"4";"5";"6";"7";"8";"9"};"")))))
This gives as output:
Now these need to be converted to hours and rounded up to one hour
EDIT 2:
Here is formula (target BZ1):
=IFERROR(IF(LEN(BZ1)-LEN(SUBSTITUTE(BZ1;" ";""))>2;LEFT(BZ1;(FIND(" ";BZ1;1)-1))+IF(TRIM(MID(SUBSTITUTE(BZ1;" ";REPT(" ";50));100;50))<60;1;1);IF(LEFT(BZ1;SUM(LEN(BZ1)-LEN(SUBSTITUTE(BZ1;{"0";"1";"2";"3";"4";"5";"6";"7";"8";"9"};""))))<60;1;1));"")
Here is a small user defined function:
Option Explicit
Public Function Tyme(inpt As String) As Double
Dim arr, U As Long
Tyme = 0
arr = Split(inpt, " ")
U = UBound(arr)
If U = 0 Then Exit Function
If U = 1 Then
Tyme = CDbl(arr(0))
Else
Tyme = CDbl(arr(0)) + CDbl(arr(2)) / 60#
End If
End Function
It:
is language-independent
returns an un-rounded floating point value (hours)
Some examples:
User Defined Functions (UDFs) are very easy to install and use:
ALT-F11 brings up the VBE window
ALT-I
ALT-M opens a fresh module
paste the stuff in and close the VBE window
If you save the workbook, the UDF will be saved with it.
If you are using a version of Excel later then 2003, you must save
the file as .xlsm rather than .xlsx
To remove the UDF:
bring up the VBE window as above
clear the code out
close the VBE window
To use the UDF from Excel:
=Tyme(A1)
To learn more about macros in general, see:
http://www.mvps.org/dmcritchie/excel/getstarted.htm
and
http://msdn.microsoft.com/en-us/library/ee814735(v=office.14).aspx
and for specifics on UDFs, see:
http://www.cpearson.com/excel/WritingFunctionsInVBA.aspx
Macros must be enabled for this to work!
NOTES:
rounding should be applied outside the udf
it would be easy to modify the udf to handle seconds as well
it would be easy to modify the udf to return true Excel time rather than floating point hours
May I suggest you use a VBA function? Seeing as in your examples there is always a space between the numbers and other characters, this should do it:
Public Function TimeInHoursRoundedUp(rng as Range)
Dim var As Variant: var = Split(rng, " ")
Dim item As Variant
Dim hour As Integer: hour = 0
For Each item In var
If IsNumeric(item) Then
If hour = 0 Then hour = hour + item Else hour = hour + 1
End If
Next item
TimeInHoursRoundedUp = hour
End Sub
Then in your excel sheet you could simply write =TimeInHoursRoundUp() and input the cell reference inside the brackets.

Visual basic - my string comparison function not working correctly

I have data like: (id,volume,median.percantile)
1 Normal Normal Low
2 Low Normal High
3 High High Normal
What I need to do is to have a counter that it increases by 1 when it is not Normal. So I expect
1 Normal Normal Low Counter:1
2 Low Normal High Counter:2
3 High High Low Counter:3
To provide it I wrote the function below. However, when I send there (Normal,Normal,High), it is calculating it 2 instead 1. So it is not working correctly. Where is my mistake?
My code is below:
Public Function getPoint(ByVal volume As String, ByVal median As String, ByVal percantile As String) As Integer
Dim Total As Integer = 0
If volume = “Normal” then
total = total + 1
end if
If median = “Normal” then
total = total + 1
end if
If percantile = “Normal” then
total = total + 1
end if
return total
End Function
In the first record, both volume and median are "Normal". So both of these conditions are true:
If volume = "Normal" Then
total = total + 1
End If
If median = "Normal" Then
total = total + 1
End If
Thus, total gets incremented twice. If you want it to be incremented only once (and essentially ignore the remaining comparisons) then use ElseIf to stop the comparisons once a condition has been satisfied:
If volume = "Normal" Then
total = total + 1
ElseIf median = "Normal" Then
total = total + 1
End If
Or just put them into a single condition:
If volume = "Normal" Or median = "Normal" Then
total = total + 1
End If
Note that this behavior is exactly the opposite of what you describe:
increases by 1 when it is not Normal
A typo perhaps?
What you are doing is opposite to what you want.
You want the count of not-Normal whereas what you are counting and returning the total is Normal.
Simple fix would be return (3 - total).
Btw, is this VBA or VB.Net? Both are based on VB but are different.
If it's VBA for Excel, you can achieve this using simple count formula (3 - count of Normal).
Change your "="'s to "<>"
i.e.
If volume <> "Normal" then
total = total + 1
End if

Using Excel's Rounddown in a UDF rounds 1 to 0

To make a long story short, the place where I work measures time by quadrants of a clock. For instance, 1.1 is an hour and 0-15 minutes, 1.2 is an hour and 15-30 minutes, and 1.3 is an hour and 30-45 minutes. There is no 1.4 because 1.4 is of course equal to 2.
I wanted to make an excel sheet that would automatically add my time under this system, so I wrote this UDF to convert the times by separating the decimal values and multiplying by 2.5 to get a normal decimal value (.1 = .25, .2 = .5, .3 = .75) and then dividing by 2.5 at the end to convert back to my employer's format. I'm aware that it can be done using excel's existing formulas, but is is kind of messy and to be honest I'm too stubborn to let this go now.
If you look at the screenshot below you'll see that the function works for all of the columns except the final weekly total column for some reason which displays 39.4 instead of 40 (again the two values are technically equivalent, but the program is not converting the .4 into a 1 for some reason).
http://i.imgur.com/yxOvlkP.png
Here is the code in it's entirety. The problem seems to occur when the remainder becomes equal to exactly 1 (for simplicity just imagine that two values ending .2 are entered) and then is rounded to zero somehow at the end.
Function newMath(week As Range) As Double
Dim time As Variant
Dim remainder As Double
Dim wholeTime As Double
remainder = 0
wholeTime = 0
For Each time In week
remainder = remainder + ((time - WorksheetFunction.RoundDown(time, 0)) * 2.5) 'Separate and sum up decimal values
wholeTime = wholeTime + WorksheetFunction.RoundDown(time, 0) 'Separate and sum up whole hours
Next time
'Problem occurs at this point when remainder = 1
'WorksheetFunction.RoundDown(remainder, 0) will equal 0 below even when 1 should round down to 1
wholeTime = wholeTime + WorksheetFunction.RoundDown(remainder, 0) 'Add the whole remainder hours to whole time
remainder = (remainder - WorksheetFunction.RoundDown(remainder, 0)) / 2.5 'Get decimal value of remainder and convert back to quadrant
newMath = wholeTime + remainder
End Function
Somehow when the remainder equals exactly 1 excel's rounddown function seems to round it to 0.
That means that the following line does not add the 1 to the whole number times as it should:
wholeTime = wholeTime + WorksheetFunction.RoundDown(remainder, 0)
And that this line will return a 1 which gets divided by 2.5 when it shouldn't (which is where the .4 comes from):
remainder = (remainder - WorksheetFunction.RoundDown(remainder, 0)) / 2.5
I'm not exactly sure what's going on or why excel is rounding my remainder of 1 to 0 if that is indeed the problem. I appreciate any help at all and let me know if you need any more information. Thanks!
Here's a slightly different way of doing things so as not to wind up with the 0.3999999 in place of the 4. Note that I used the VBA Int function which should execute more rapidly than the worksheetfunction.roundown(n,0).
By multiplying time * 10, and then, with the Mod function summing the last digit, we can do integer math until it is time to convert back to the final result.
Also note that the below routine is designed for positive numbers only. If you may be having negative numbers on your time sheet, you should use Fix in place of Int
Option Explicit
Function newMath(week As Range) As Double
Dim time As Range
Dim remainder As Variant
Dim wholeTime As Long
remainder = 0
wholeTime = 0
For Each time In week
wholeTime = wholeTime + Int(time)
remainder = remainder + (time * 10) Mod 10
Next time
'Problem occurs at this point when remainder = 1
'WorksheetFunction.RoundDown(remainder, 0) will equal 0 below even when 1 should round down to 1
wholeTime = wholeTime + Int(remainder / 4) 'Add the whole remainder hours to whole time
remainder = ((remainder / 4) - Int(remainder / 4)) / 2.5 'Get decimal value of remainder and convert back to quadrant
newMath = wholeTime + remainder
End Function
Try this code:
Function newMath(Rng As Range) As Double
Dim CL As Range
Dim hs As Long, hs1 As Long
Dim ms As Double, ms1 As Double, ms2 As Double
For Each CL In Rng
hs = hs + Fix(CL.Value)
ms = ms + CL.Value
Next
ms1 = Round((ms - hs), 1)
hs1 = Fix(ms1 / 0.4)
ms2 = ms1 - (hs1 * 0.4)
newMath = hs + hs1 + ms2
End Function

Random shuffling of elements in an array between 2 indexes VB.NET

I'm trying to shuffle elements between a certain number of indexes.
Dim rng As New Random()
For placeHolder As Integer = min To max Step -1
Dim swapIndex As Integer = rng.Next(min, max)
Dim temp As Object = myList(placeHolder)
myList(placeHolder) = myList(swapIndex)
myList(swapIndex) = temp
Next
Where 'min' is the value of the lowest index and 'max' is the value of the highest index. However each time I have tried it doesn't seem to be shuffling randomly (it always comes out alphabetically instead).
Try this:
Dim rng As New Random()
For placeHolder as Integer = min To max-1 Step 1
Dim swapIndex as Integer = rng.Next(placeHolder +1, max)
Dim temp as Object = myList(placeHolder)
myList(placeHolder) = myList(swapIndex)
myList(swapIndex) = temp
Next
The changes?
I changed the max value being stepped over to 1 less than the end so that you don't waste time trying to swap the end with itself. I also changed the Step to +1 because min < max from your description. I changed the minimum random value to placeholder + 1 because I don't want to re-swap what I've already swapped. This last change is optional though.
if min is the lowest and max is the highest, then your loop should not have Step -1 in it. That will cause the loop to never execute.

Calculating the sum of number difference within a for loop in vb.net

I have a dataset which includes some numbers, I want to calculate the sum of the difference in the numbers how do I do this?
For example my dataset looks like this:
Name Score
Luke 100
Adam 90
James 80
Peter 70
Mike 60
How do I calculate the sum of the difference within a “for loop” in vb.net such that it does something like this below:
(100 - 90) + (90 – 80) + (80 – 70) + (70 – 60) = 40
I tried to do this below, but i am not sure of how to add the difference:
Dim i as integer
For i = 0 to ds.tables(0).rows.count
ds.tables(0).Row(i).Item(1)
Dim diff = ds.tables(0).Row(i).Item(1) - ds.tables(0).Row(i+1).Item(1)
sum = ....
Next
Any help will be appreciated
You can try this,
Dim totalValue As Integer = 0
For index = 1 To ds.Tables(0).Rows.Count
totalValue += (CInt(ds.Tables(0).Rows(index - 1).Item(1)) - CInt(ds.Tables(0).Rows(index).Item(1)))
Next
You can use totalValue as your answer
First, you need to stop the loop before you reach the count, otherwise you will receive an exception.
Second, you need to add a special case for the first item:
' The sum of the differences
Dim wSumOfDifferences As Integer
' Start with a non-sensical value for the last value that we processed
Dim wLastValue As Integer = -1
For Each oRow As DataRow in ds.Tables(0).Rows
Dim wCurrValue As Integer
' Get the current value
wCurrValue = CInt(oRow.Item(1))
' If we are not working on the first item, calculate the difference between
' the current value and the last value
If wLastValue <> -1 Then
wSumOfDifferences += (wLastValue - wCurrValue)
End If
' Record the current value as the last value
wLastValue = wCurrValue
Next
Console.WriteLine("Sum = " & CStr(wSumOfDifferences))