MS Access newbie here. I've written a VBA UDF to calculate an AQL Sample Size by the Inspection Level (IL Variable in my code), and Lot size (Batch Variable in my code)
In an access userform, I have the two values for my two variables displayed in a text box. I then have a third text box which has my UDF in it, and that I want to auto-update to the new value, when I add or change either of the two variables, but it never changes. It just stays on zero.
When I update either variable, if I put a stop in the UDF VBA code, the code does run, and provides me with the correct answer in a Watch in my VBE as I step through it. So the code seems to be OK, I'm assuming. Just something I'm doing wrong in the text box properties I'm trying to return the value in, I'm guessing.
The code is below if it helps.
Also, somewhat related question, I'm guessing you cannot use a UDF in a table? I can use the same UDF in an excel table, so I was thinking I should be able to, but it appears I cannot.
Thanks
Public Function SampleSize(IL As String, Batch As Long) As Long
If IL = "S1" Then
Select Case Batch
Case 2 To 50
Sample = 2
Case 51 To 500
Sample = 3
Case 501 To 35000
Sample = 5
Case Is >= 35001
Sample = 8
End Select
End If
If IL = "S2" Then
Select Case Batch
Case 2 To 25
Sample = 2
Case 26 To 150
Sample = 3
Case 151 To 1200
Sample = 5
Case 1201 To 35000
Sample = 8
Case Is >= 35001
Sample = 13
End Select
End If
If IL = "S3" Then
Select Case Batch
Case 2 To 15
Sample = 2
Case 16 To 50
Sample = 3
Case 51 To 150
Sample = 5
Case 151 To 500
Sample = 8
Case 501 To 3200
Sample = 13
Case 3201 To 35000
Sample = 20
Case 35001 To 500000
Sample = 32
Case Is >= 500001
Sample = 50
End Select
End If
If IL = "S4" Then
Select Case Batch
Case 2 To 15
Sample = 2
Case 16 To 25
Sample = 3
Case 26 To 90
Sample = 5
Case 91 To 150
Sample = 8
Case 151 To 500
Sample = 13
Case 501 To 1200
Sample = 20
Case 1201 To 10000
Sample = 32
Case 10001 To 35000
Sample = 50
Case 35001 To 500000
Sample = 80
Case Is >= 500001
Sample = 125
End Select
End If
If IL = "G1" Then
Select Case Batch
Case 2 To 15
Sample = 2
Case 16 To 25
Sample = 3
Case 26 To 90
Sample = 5
Case 91 To 150
Sample = 8
Case 151 To 280
Sample = 13
Case 281 To 500
Sample = 20
Case 501 To 1200
Sample = 32
Case 1201 To 3200
Sample = 50
Case 3201 To 10000
Sample = 80
Case 10001 To 35000
Sample = 125
Case 35001 To 150000
Sample = 200
Case 150001 To 500000
Sample = 315
Case Is >= 500001
Sample = 500
End Select
End If
If IL = "G2" Then
Select Case Batch
Case 2 To 8
Sample = 2
Case 9 To 15
Sample = 3
Case 16 To 25
Sample = 5
Case 26 To 50
Sample = 8
Case 51 To 90
Sample = 13
Case 91 To 150
Sample = 20
Case 151 To 280
Sample = 32
Case 281 To 500
Sample = 50
Case 501 To 1200
Sample = 80
Case 1201 To 3200
Sample = 125
Case 3201 To 10000
Sample = 200
Case 10001 To 35000
Sample = 315
Case 35001 To 150000
Sample = 500
Case 150001 To 500000
Sample = 800
Case Is >= 500001
Sample = 1250
End Select
End If
If IL = "G3" Then
Select Case Batch
Case 2 To 8
Sample = 3
Case 9 To 15
Sample = 5
Case 16 To 25
Sample = 8
Case 26 To 50
Sample = 13
Case 51 To 90
Sample = 20
Case 91 To 150
Sample = 32
Case 151 To 280
Sample = 50
Case 281 To 500
Sample = 80
Case 501 To 1200
Sample = 125
Case 1201 To 3200
Sample = 200
Case 3201 To 10000
Sample = 315
Case 10001 To 35000
Sample = 500
Case 35001 To 150000
Sample = 800
Case 150001 To 500000
Sample = 1250
Case Is >= 500001
Sample = 2000
End Select
End If
End Function
You never assign a return value to the function itself!
You should place this line of code as indicated:
SampleSize = Sample
End Function
Also it is good practice to declare variables within the scope of your function.
Dim Sample As Long
When declared it will be initialized to 0, which will also be your default return value and the same Type as your Function.
Undeclared variables will be Variant type and initialized to Empty...
Related
I am using Big query to extract results from employee learning table. I need to figure out if an employee has completed a set of courses for a department. For example if an employee complete all of these three courses say, course 100, course 200 and course 300, they can be classified as as compliant else They are non-compliant. I have created a dummy example of how my data is structured, unfortunately due to organization policy I cant share more information.
Problem statement.
Say employee who has completed course 100,200,300 They are compliant in Bakery else they are non-complaint. Employee must complete all three courses to be compliant.
Employee who has completed course 100 and 300 They are compliant in Fruit & Veg else they are non-complaint. They must complete above mention two courses to be compliant.
Employee who has completed course 75,85,95 They are compliant in Grocery else non-compliant. Same here they must have done three courses so that they can be compliant.
Employee who has completed 101 and 102 They are compliant in Nighfill else non-compliant.
Please note employee must complete all the sets to be compliant in relevant categories
Employee course
1 100
1 101
1 200
1 300
1 300
1 400
2 100
2 200
3 100
3 200
3 300
4 75
4 85
4 95
4 105
4 115
4 125
5 200
5 200
5 100
5 100
5 100
5 300
5 300
6 100
7 100
8 300
8 200
8 100
8 101
8 102
9 100
9 200
9 300
Structure of Data
I am still thinking about the solution.
Consider below approach
select Employee,
ifnull(array_length(split(string_agg(distinct if(course in (100,200,300), '' || course, null)))), 0) = 3 isBakeyCompliant,
ifnull(array_length(split(string_agg(distinct if(course in (100,300) and not course in (200), '' || course, null)))), 0) = 2 isFruitVegCompliant,
ifnull(array_length(split(string_agg(distinct if(course in (75,85,95), '' || course, null)))), 0) = 3 isGroceryCompliant,
ifnull(array_length(split(string_agg(distinct if(course in (101,102), '' || course, null)))), 0) = 3 isNighfillCompliant,
from your_table
group by Employee
with output
Bonjour,
I am trying to apply the χ2 test by contingency table from the exploratory statistics course to the results given in Example 1 from Wikipedia.
Rolling a die 600 times in a row gave the following results:
number rolled 1 2 3 4 5 6
numbers 88 109 107 94 105 97
The number of degrees of freedom is 6 - 1 = 5.
We wish to test the hypothesis that the die is not rigged, with a risk α = 0.05.
The null hypothesis here is therefore: "The die is balanced".
Considering this hypothesis to be true, the variable T defined above is : ( 88 - 100 ) 2 100 + ( 109 - 100 ) 2 100 + ( 107 - 100 ) 2 100 + ( 94 - 100 ) 2 100 + ( 105 - 100 ) 2 100 + ( 97 - 100 ) 2 100 = 3 , 44
The χ2 distribution with five degrees of freedom gives the value below which we consider the draw to be compliant with a risk α = 0.05: P(T < 11.07) = 0.95.
Since 3.44 < 11.07, we cannot reject the null hypothesis: this statistical data does not allow us to consider that the die is rigged.
I tried to retrieve this result with pandas:
dico = {' face ' : [1,2,3,4,5,6], ' numbers ' : [88, 109, 107, 94, 105, 97]} #[100, 100, 101, 99, 101, 99]}
tab = pd.DataFrame(dico)
print(tab.head(6))
ta = pd.crosstab(tab[' face '],tab[' numbers '])
print(ta)
test = chi2_contingency(tab)
test
face numbers 0 1 88 1 2 109 2 3 107 3 4 94 4 5 105 5 6 97 numbers 88 94 97 105 107 109 face 1 1 0 0 0 0 0 0 2 0 0 0 0 0 1 3 0 0 0 0 1 0 4 0 1 0 0 0 0 5 0 0 0 1 0 0 6 0 0 1 0 0 0
(4.86, 0.432, 5)
This is not the expected result. (with ta, it is the same)
then I present the problem as follows:
dico = {' error ' : [-12, 9, 7, -6, 5, -3], ' number ' : [88, 109, 107, 94, 105, 97]} #[100, 100, 101, 99, 101, 99]}
tab = pd.DataFrame(dico)
print(tab.head(6))
ta = pd.crosstab(tab[' error '],tab[' staff '])
test
error numbers 0 -12 88 1 9 109 2 7 107 3 -6 94 4 5 105 5 -3 97
(10.94, 0.052, 5)...same...I expect something like (3.44, p-value should be between 0.5 and 0.9, 5)
Something is wrong but What?
Regards,
Leloup
I have the following function:
def sum(x):
oneS = x.iloc[0:len(x)//10].agg('sum')
twoS = x.iloc[len(x)//10:2*len(x)//10].agg('sum')
threeS = x.iloc[2*len(x)//10:3*len(x)//10].agg('sum')
fourS = x.iloc[3*len(x)//10:4*len(x)//10].agg('sum')
fiveS = x.iloc[4*len(x)//10:5*len(x)//10].agg('sum')
sixS = x.iloc[5*len(x)//10:6*len(x)//10].agg('sum')
sevenS = x.iloc[6*len(x)//10:7*len(x)//10].agg('sum')
eightS = x.iloc[7*len(x)//10:8*len(x)//10].agg('sum')
nineS = x.iloc[8*len(x)//10:9*len(x)//10].agg('sum')
tenS = x.iloc[9*len(x)//10:len(x)//10].agg('sum')
return [oneS,twoS,threeS,fourS,fiveS,sixS,sevenS,eightS,nineS,tenS]
How to assign the outputs of this function to columns of dataframe (which already exists)
The dataframe I am applying the function is as below
Cycle Type Time
1 1 101
1 1 102
1 1 103
1 1 104
1 1 105
1 1 106
9 1 101
9 1 102
9 1 103
9 1 104
9 1 105
9 1 106
The dataframe I want to add the columns is something like below & the new columns Ones, TwoS..... Should be added like shown & filled with the results of the function.
Cycle Type OneS TwoS ThreeS
1 1
9 1
8 1
10 1
3 1
5 2
6 2
7 2
If I write a function for just one value and apply it like the following, it is possible:
grouped_data['fm']= data_train_bel1800.groupby(['Cycle', 'Type'])['Time'].apply( lambda x: fm(x))
But I want to do it all at once so that it is neat and clear.
You can use:
def f(x):
out = []
for i in range(10):
out.append(x.iloc[i*len(x)//10:(i+1)*len(x)//10].agg('sum'))
return pd.Series(out)
df1 = (data_train_bel1800.groupby(['Cycle', 'Type'])['Time']
.apply(f)
.unstack()
.add_prefix('new_')
.reset_index())
print (df1)
Cycle Type new_0 new_1 new_2 new_3 new_4 new_5 new_6 new_7 new_8 \
0 1 1 0 101 102 205 207 209 315 211 211
1 9 1 0 101 102 205 207 209 315 211 211
new_9
0 106
1 106
I have a gritty industrial control problem i'm trying to solve with T-SQL.
The goal is to calculate an index position for each of two pallet loading robots, positioned in one of two ranges; 2 to 78 (robot 1) and 4 to 80 (robot 2).
Each robot indexes in steps of 4 so complete coverage of 80 spots on the pallet is achieved. The robots work side by side with a minimum spacing of 2 spots while they move along the pallet.
Two sized boxes can be placed on the pallet, one twice as long as the other. If two small boxes are placed side by side taking up 1 spot each, a single larger box can be placed on top, taking up 2 spots until a maximum height is reached. Thus the spot number for a small box is always odd and for a large box is always even and the robot index number is always even. e.g. (see diagram) from index position 14 spots 13 and 15 are loaded, and from index 20 spots 19 and 21 can be loaded.
Robot Index Positions
I need a conversion formula that calculates the Index number for a given Spot and Robot.
The calculated Index column should look like the following:
Spot Robot Index
1 1 2
2 1 2
3 1 2
- - -
13 1 14
14 1 14
15 1 14
16 2 16
17 2 16
18 1 18
19 2 20
- - -
- - -
77 1 78
78 1 78
79 2 80
80 2 80
One way would be to do an update to the Index column with every possible combination of Spot and Robot using a simple CASE WHEN selection or maybe do lookups on a reference table holding every possible combination. What I would like to explore (if any math wizards are inclined!) is a math formula that calculate the Index value.
So far I've come up with the following by converting formula developed for use in Excel. The Robot 2 section is incomplete. The 95 to 99 values are for error checking.
UPDATE MovesTable SET [Index] =
CASE
WHEN Robot = 1 THEN
CASE
WHEN Spot%4 = 0 THEN '99'
WHEN Spot = 1 or Spot = 2 or Spot = 3 THEN '02'
WHEN Spot = 5 or Spot = 6 or Spot = 7 THEN '06'
WHEN Spot = 9 or Spot = 10 or Spot = 11 THEN '10'
WHEN Spot%10 = 4 THEN CONCAT(Spot/10,'4')
WHEN Spot < 57 AND (((Spot/10)%2 = 1 AND (Spot%10)%2 = 1) AND (Spot%10 = 3 OR Spot%10 = 5)) THEN CONCAT(Spot/10,'4')
WHEN Spot%10 = 8 THEN CONCAT(Spot/10,'8')
WHEN Spot < 57 AND (((Spot/10)%2 = 1 AND (Spot%10)%2 = 1) AND (Spot%10 = 7 OR Spot%10 = 9)) THEN CONCAT(Spot/10,'8')
WHEN Spot%10 = 2 THEN CONCAT(Spot/10,'2')
WHEN Spot < 57 AND (((Spot/10)%2 = 1 AND (Spot%10)%2 = 0) AND (Spot%10 = 1 OR Spot%10 = 3)) THEN CONCAT(Spot/10,'2')
WHEN Spot%10 = 6 THEN CONCAT(Spot/10,'6')
WHEN Spot < 57 AND (((Spot/10)%2 = 0 AND (Spot%10)%2 = 1) AND (Spot%10 = 5 OR Spot%10 = 7)) THEN CONCAT(Spot/10,'6')
WHEN Spot%10 = 0 THEN CONCAT(Spot/10,'')
WHEN Spot = 49 THEN '50'
WHEN Spot < 57 AND (((Spot/10)%2 = 0 AND (Spot%10)%2 = 1) AND Spot%10 = 9) THEN '30'
WHEN Spot < 57 AND (((Spot/10)%2 = 1 AND (Spot%10)%2 = 1) AND Spot%10 = 1) THEN CONCAT(Spot/10,'0')
WHEN Spot > 56 AND (((Spot/10)%2 = 1 AND (Spot%10)%2 = 1) AND (Spot%10 = 7 OR Spot%10 = 9)) THEN CONCAT(Spot/10,'8')
WHEN Spot > 56 AND (((Spot/10)%2 = 0 AND (Spot%10)%2 = 1) AND (Spot%10 = 1 OR Spot%10 = 3)) THEN CONCAT(Spot/10,'2')
WHEN Spot > 56 AND (((Spot/10)%2 = 0 AND (Spot%10)%2 = 1) AND (Spot%10 = 5 OR Spot%10 = 7)) THEN CONCAT(Spot/10,'6')
ELSE '98'
END
ELSE
CASE
WHEN Robot = 2 THEN
CASE
WHEN (Spot%2 = 0 AND Spot%4 <> 0) OR (Spot = 1 OR Spot = 2) THEN '97'
WHEN Spot = 4 then '04'
WHEN Spot = 8 then '08'
WHEN Spot%4 = 0 THEN Spot
WHEN Spot = 2 OR Spot = 5 THEN '05'
WHEN Spot = 7 OR Spot = 9 THEN '08'
WHEN Spot = 19 THEN '20'
WHEN Spot = 39 THEN '40'
WHEN Spot = 59 THEN '60'
ELSE '96'
END
ELSE '95'
END
END
I tried to solve this mathematically, rather than by analyzing cases, etc. It matches all of your sample results:
declare #t table (Spot int, Robot int, [Index] int)
insert into #t(Spot,Robot,[Index]) values
(1 ,1 , 2 ),
(2 ,1 , 2 ),
(3 ,1 , 2 ),
(13 ,1 ,14 ),
(14 ,1 ,14 ),
(15 ,1 ,14 ),
(16 ,2 ,16 ),
(17 ,2 ,16 ),
(18 ,1 ,18 ),
(19 ,2 ,20 ),
(77 ,1 ,78 ),
(78 ,1 ,78 ),
(79 ,2 ,80 ),
(80 ,2 ,80 )
select *,
CONVERT(int,
ROUND((Spot +
CASE WHEN Robot = 1 THEN 2 ELSE 0 END
)/4.0,0)* 4 -
CASE WHEN Robot = 1 THEN 2 ELSE 0 END
) as Index2
from #t
The logic is "round to the nearest multiple of four" but we use a couple of expressions to offset Robot 1's results by 2.
Results:
Spot Robot Index Index2
----------- ----------- ----------- -----------
1 1 2 2
2 1 2 2
3 1 2 2
13 1 14 14
14 1 14 14
15 1 14 14
16 2 16 16
17 2 16 16
18 1 18 18
19 2 20 20
77 1 78 78
78 1 78 78
79 2 80 80
80 2 80 80
CREATE TABLE TEMP(RESOURCE_VALUE VARCHAR2(63 BYTE),TOT_COUNT NUMBER)
I want an query which can extract the range from which to which I want to have breakup of the sum records to XYZ value. I will say 50,000 is the break up need. Then it has to display all the ranges from which RESOURCE_VALUE to which RESOURCE_VALUE I can get sum <=50,000. One RESOURCE_VALUE value can be included in only one range.
Example: sample data
The Below Is The input
resource_value | tot_count
---------------+----------
1 100
2 50
3 20
4 30
5 300
6 250
7 200
8 30
9 60
10 200
11 110
12 120
Then the output has to be something like this :
sample output 1: when sum(tot_count)<=300
start resource_value endresource_value sum
---------------------+---------------------+-------
1 4 300
5 5 300
6 6 250
7 9 290
10 10 200
11 12 230
sample output 2: when sum(tot_count)<=500
start resource_value end resource_value sum
---------------------+---------------------+------
1 4 300
5 5 300
6 8 480
9 12 490
I just guess that you use ORACLE, because of your table structure, and in oracle you can use this query to get your aim:
with vw1(val,flg,sumval) as
(select 1 val,0 flg,TOT_COUNT sumval
from TEMP where RESOURCE_VALUE = '1'
union all
select vw1.val + 1 val,
case when vw1.sumval + t1.TOT_COUNT > 300 then vw1.flg + 1 else vw1.flg end flg,
case when vw1.sumval + t1.TOT_COUNT > 300 then t1.TOT_COUNT else vw1.sumval + t1.TOT_COUNT end sumval
From TEMP t1,vw1 WHERE t1.RESOURCE_VALUE = TO_CHAR(vw1.val + 1))
select min(val) START_RESOURCE_VALUE,max(val) END_RESOURCE_VALUE,
max(sumval) "SUM" from vw1 group by flg order by min(val);
SQL Fiddle