Solved Code wont run correctly unless stepping through with breakpoints? (1 Viewer)

Sam Summers

Registered User.
Local time
Today, 13:03
Joined
Sep 17, 2001
Messages
939
Hi Guys, another week of trying to fix this! I tried the decompile option of the Doc Man's but still no luck.

I found the original error where for some reason the ServiceHour field was set to Date/Time but even after changing it back and starting again the code is still not recognising it at all so my idea now its to completely delete 'ServiceHour', decompile, compact and repair and then create a new option to replace 'ServiceHour'
 

theDBguy

I’m here to help
Staff member
Local time
Today, 06:03
Joined
Oct 29, 2018
Messages
21,357
Hi Guys, another week of trying to fix this! I tried the decompile option of the Doc Man's but still no luck.

I found the original error where for some reason the ServiceHour field was set to Date/Time but even after changing it back and starting again the code is still not recognising it at all so my idea now its to completely delete 'ServiceHour', decompile, compact and repair and then create a new option to replace 'ServiceHour'
Hi. Good luck with your next step. Just let me know if you want to try my idea, if you don't find a working solution.
 

Sam Summers

Registered User.
Local time
Today, 13:03
Joined
Sep 17, 2001
Messages
939
I found out why 'ServiceHour' produces a type mismatch!!

Its because i have the Control Source set to "=[Divider]*[ServiceInterval]" which is to ensure that the service interval is updated once each service interval has been passed

So i need to find another way of doing this?
 

Sam Summers

Registered User.
Local time
Today, 13:03
Joined
Sep 17, 2001
Messages
939
Well unfortunately nothing works now so i think i have to scrap the whole thing
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 09:03
Joined
May 21, 2018
Messages
8,463
Before you go to far, can you post a database? Also did you change the event as suggested. Again if you are only calling this on the form On Load event, it is not really doing anything. It runs once and likely there are no values yet to use in the calculation, or it is just updated one record.
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 08:03
Joined
Feb 28, 2001
Messages
26,996
I found out why 'ServiceHour' produces a type mismatch!!

Its because i have the Control Source set to "=[Divider]*[ServiceInterval]" which is to ensure that the service interval is updated once each service interval has been passed

So i need to find another way of doing this?

When you set the control source to an equation, you are locking yourself down. There IS a difference between bound, unbound, and computed values as control sources, and you just tripped over one of them.

But there is always the chance that you could have something in the FORM_CURRENT event that looks at the particular control and if it is blank, assert its value using that formula. But since it is not asserted in the control source, you can edit the field happily and it will retain the edited value. Of course, there is the issue of what you do with it later, but this might help you make a little more progress without totally scrapping everything.
 

Sam Summers

Registered User.
Local time
Today, 13:03
Joined
Sep 17, 2001
Messages
939
Before you go to far, can you post a database? Also did you change the event as suggested. Again if you are only calling this on the form On Load event, it is not really doing anything. It runs once and likely there are no values yet to use in the calculation, or it is just updated one record.
So i have tried things OnCurrent and OnLoad and various things as you will see in the attached DB its all in the 'ViewServiceHistory' form which normally opens from the 'Service' Tab on the 'ViewVessel' form.

You will need to use the bypass key to open it.
 

Attachments

  • Tanera Fleet Management.zip
    615.8 KB · Views: 79

MajP

You've got your good things, and you've got mine.
Local time
Today, 09:03
Joined
May 21, 2018
Messages
8,463
I am having a hard time wrapping my head around how this is supposed to work. I am not sure if I understand the fields and how you use them.

Component Component

ComponentIDVesselIDComponentNameServiceIntervalWarningAtFlagInterval
1​
Main Engine
250​
175​
75​
2​
Genset
250​
175​
75​
Every 250 hours the Main Engine gets serviced. You get a warning at 175 and a flag after 75.

In the service table how you record information is unclear.

Service Service

ServiceIDVesselIDComponentIDTechIDServicedIDServiceDateCostRecordedHoursServiceHourFlagIntervalDivider
19​
1​
Main EngineAngus Mackenzie
08/07/21​
12​
20​
1​
GensetDan Walton
11/07/21​
237​
24​
1​
GensetAngus Mackenzie
07/12/21​
83​
Are the recorded hours a running sum? For the Genset was there 83 hours on 7/12 and then on the meter 237 on 11/07? I asked this because you are summing all these hours for all components, which makes no sense to me. I would think I would only care about the most current meter reading and the last service hour.

I interpret that Genset has never been serviced and it is due at 250 hours minus 237. If there was service hours listed I would need the service hour for the last service. Lets just say it was serviced at 200. Then the next service is due 200 + 250 - 237. It would warn at 200 + 175.

This is what I think should happen, but I do not see anything close to doing that. The calculation on your form do not make any sense since you are taking total hours as the sum of all recorded hours for all components. That number seems meaningless, unless there is a very different logic than I am expecting.
 

Sam Summers

Registered User.
Local time
Today, 13:03
Joined
Sep 17, 2001
Messages
939
I am having a hard time wrapping my head around how this is supposed to work. I am not sure if I understand the fields and how you use them.

Component Component

ComponentIDVesselIDComponentNameServiceIntervalWarningAtFlagInterval
1​
Main Engine
250​
175​
75​
2​
Genset
250​
175​
75​
Every 250 hours the Main Engine gets serviced. You get a warning at 175 and a flag after 75.

In the service table how you record information is unclear.

Service Service

ServiceIDVesselIDComponentIDTechIDServicedIDServiceDateCostRecordedHoursServiceHourFlagIntervalDivider
19​
1​
Main EngineAngus Mackenzie
08/07/21​
12​
20​
1​
GensetDan Walton
11/07/21​
237​
24​
1​
GensetAngus Mackenzie
07/12/21​
83​
Are the recorded hours a running sum? For the Genset was there 83 hours on 7/12 and then on the meter 237 on 11/07? I asked this because you are summing all these hours for all components, which makes no sense to me. I would think I would only care about the most current meter reading and the last service hour.

I interpret that Genset has never been serviced and it is due at 250 hours minus 237. If there was service hours listed I would need the service hour for the last service. Lets just say it was serviced at 200. Then the next service is due 200 + 250 - 237. It would warn at 200 + 175.

This is what I think should happen, but I do not see anything close to doing that. The calculation on your form do not make any sense since you are taking total hours as the sum of all recorded hours for all components. That number seems meaningless, unless there is a very different logic than I am expecting.
Thank you for your reply. sorry for the confusion. I shall explain -

You will see that there are a few vessels and some have different components than the others.
The user sets the service interval on entry of the components for each vessel so the service intervals will vary but you are correct that the component for each vessels recorded hours is a running sum.

Initially the user wanted me to flag up 75 hours before the service interval and hence i was trying to think of a way to do that so had 250 - 75 which is the 175 but now i think it is better and easier to simply indicate constantly when the service is due which will cover this anyway. So i think the 'WarningAt' and 'FlagInterval' fields are redundant now.

So initially the service interval will be 250, 300 or 500 and maybe others depending on the component so a simple subtraction of the running sum is easy but once the service interval is passes then i have to add the next service interval to it and so on with the next interval which is why i was trying to do this with the 'Service Hour' field.

With my limited ability i have struggled with this.

I hope that this helps?
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 09:03
Joined
May 21, 2018
Messages
8,463
I think I understand but I am confused because what you seem to be trying is not what I would expect.

Recorded hours means the hours reading when the component was serviced? So even though the main engine should be serviced every 250 hours it was serviced at only 12 hours. Is that right? The way I interpret the data that you are showing is that for Genset for Vessel 1 it has a service interval at 250 hours. For some reason it was serviced early at 83 hours and then at 237. Do recorded hours mean it was serviced at that time? Do you record current hours somewhere? Because originally that is what I thought. I thought recorded hours was just a periodic review and service hours was time it was serviced, but I think not now.

What I am thinking you do not need fields for Service Hour (I think this is next service due), Warning at, and Flag Interval.

I do think you need to completely fill in your component table. That means your component table is really a "Vessel_Components". Currently you did not fill in the vessel id. This table will then have all the components for all vessels listed. So if each vessel has a main engine then there needs to be a main engine record for each vessel. So each component ID is not just a generic component but the ID represents that specific component in that vessel. So vesselID needs to be required in your component table and referential integrity enforced.

In your service table you would not need the vessel id, because when you select a specific component that relationship to the vessel comes from the component table.

So if you have listed in the component table all the components for a vessel and the recorded hours in the service table (representing when service performed) you should be able to show a query that selects the Max recorded hours for each component which is the hours when last serviced. This will be 0 for components that have not yet been serviced. Then the next service due is simply service interval + max recorded hours. Remaining hours would be Service Interval + Max Recorded Hours - Current Hours (if this exists somewhere)
So in your case


This is how I think it would work, but does not appear to be what you are trying to do. So if all the components for each vessel where listed then I expect to see something like

Vessel: Vessel 1
Component: Main Engine
Last Service hrs: 12hrs
Last Service Date : 08/07/21
Next Service: 262

Vessel: Vessel 1
Component: GenSet
Last Service hrs: 237 hrs
Last Service Date :11/07/21
Next Service: 487

.... all other components
Is that the correct interpretation. If so I have almost the same already done in an inspection database. Different inspections have different intervals, and different buildings have different types of inspections. Based on last inspection it shows next date inspection due for each type of inspection for each building.
 

Sam Summers

Registered User.
Local time
Today, 13:03
Joined
Sep 17, 2001
Messages
939
I think I understand but I am confused because what you seem to be trying is not what I would expect.

Recorded hours means the hours reading when the component was serviced? So even though the main engine should be serviced every 250 hours it was serviced at only 12 hours. Is that right? The way I interpret the data that you are showing is that for Genset for Vessel 1 it has a service interval at 250 hours. For some reason it was serviced early at 83 hours and then at 237. Do recorded hours mean it was serviced at that time? Do you record current hours somewhere? Because originally that is what I thought. I thought recorded hours was just a periodic review and service hours was time it was serviced, but I think not now.

What I am thinking you do not need fields for Service Hour (I think this is next service due), Warning at, and Flag Interval.

I do think you need to completely fill in your component table. That means your component table is really a "Vessel_Components". Currently you did not fill in the vessel id. This table will then have all the components for all vessels listed. So if each vessel has a main engine then there needs to be a main engine record for each vessel. So each component ID is not just a generic component but the ID represents that specific component in that vessel. So vesselID needs to be required in your component table and referential integrity enforced.

In your service table you would not need the vessel id, because when you select a specific component that relationship to the vessel comes from the component table.

So if you have listed in the component table all the components for a vessel and the recorded hours in the service table (representing when service performed) you should be able to show a query that selects the Max recorded hours for each component which is the hours when last serviced. This will be 0 for components that have not yet been serviced. Then the next service due is simply service interval + max recorded hours. Remaining hours would be Service Interval + Max Recorded Hours - Current Hours (if this exists somewhere)
So in your case


This is how I think it would work, but does not appear to be what you are trying to do. So if all the components for each vessel where listed then I expect to see something like

Vessel: Vessel 1
Component: Main Engine
Last Service hrs: 12hrs
Last Service Date : 08/07/21
Next Service: 262

Vessel: Vessel 1
Component: GenSet
Last Service hrs: 237 hrs
Last Service Date :11/07/21
Next Service: 487

.... all other components
Is that the correct interpretation. If so I have almost the same already done in an inspection database. Different inspections have different intervals, and different buildings have different types of inspections. Based on last inspection it shows next date inspection due for each type of inspection for each building.
Hi again and thank you.

The components that are filled in just now is only me testing the code. When the users first populate the system they will enter the service intervals for each component depending on the components for each vessel.

Each vessel has different components.

The Recorded Hours are entered after the vessel is used and so are accumulative
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 09:03
Joined
May 21, 2018
Messages
8,463
What does recorded hours mean and when is it logged? Is this an accumulative number (like an hour gauge) or is this how long it ran since the last entry?
You say you log both elapsed and cumulative. Which fields?
Now I get a sense that recorded hours is elapsed time and not cummulative. So for Genset it ran 12 + 237, not 237 as the last reading. If the vessel gets used would all components get an entry after use?
What does service hours represent?
It would be a lot more helpful if you filled in a representative set of data needed to do this. With all the empty fields I am guessing what your process is.
 

Sam Summers

Registered User.
Local time
Today, 13:03
Joined
Sep 17, 2001
Messages
939
What does recorded hours mean and when is it logged? Is this an accumulative number (like an hour gauge) or is this how long it ran since the last entry?
You say you log both elapsed and cumulative. Which fields?
Now I get a sense that recorded hours is elapsed time and not cummulative. So for Genset it ran 12 + 237, not 237 as the last reading. If the vessel gets used would all components get an entry after use?
What does service hours represent?
It would be a lot more helpful if you filled in a representative set of data needed to do this. With all the empty fields I am guessing what your process is.
So recorded hours is an hour gauge. So yes genset is 12 + 237 as you said.

Most components would be used when a vessel is used but not always so it is the user who must log the hours after each use of whichever component (or all) that are used.

ServiceHour is what i am trying to increase by the service interval (for example 250) once the next service interval has been reached or passed.

I know my code is not great but here is a slightly cleaned up version that actually works perfectly but only when i set breakpoints and step through it?

Code:
    Dim a As Integer
    Dim b As Integer
    Dim c As Integer
    Dim answer As Integer
    Dim answer2 As Integer
    Dim answer3 As Integer
    Dim answer4 As Integer
    Dim MyVar, MyVar2

    MyVar = Me.TotalHours.Value
    MyVar2 = Me.ServiceInterval.Value

    a = Me.TotalHours.Value
    b = Me.ServiceInterval.Value
    If IsNull(MyVar2) Or MyVar2 = "" Then
 '       MsgBox "There are no hours currently recorded for this component", vbInformation, "Tanera Fleet Management System"
        Exit Sub
    Else
        If a < b Then
            answer2 = b - a
            Me.DueIn.Value = answer2
        Else
            answer = a / b
            Me.Divider.Value = answer
            c = Me.ServiceHour.Value

            If a > c Then
                answer3 = b + c
                answer4 = answer3 - a
                Me.DueIn.Value = answer4
            Else

            End If
        End If
    End If

I am finished for the day now but maybe tomorrow i may finally solve this?
 

Sam Summers

Registered User.
Local time
Today, 13:03
Joined
Sep 17, 2001
Messages
939
Hi everyone i woke up with an idea this morning and it worked.

So i removed the 'FlagInterval' and 'WarningAt' fields completely.

I also removed the '=[Divider]*[ServiceInterval] from the 'ServiceHour' Control Source and inserted this line in the code:
Me.ServiceHour.Value = Me.ServiceInterval.Value

This was my final code that works perfectly

Code:
Private Sub Form_Current()

    Dim a As Integer
    Dim b As Integer
    Dim c As Integer
    Dim answer As Integer
    Dim answer2 As Integer
    Dim answer3 As Integer
    Dim answer4 As Integer

    Me.ServiceHour.Value = Me.ServiceInterval.Value

    a = Me.TotalHours.Value
    b = Me.ServiceInterval.Value

        If a < b Then
            answer2 = b - a
            Me.DueIn.Value = answer2
        Else
            answer = a / b
            Me.Divider.Value = answer
            c = Me.ServiceHour.Value

            If a > c Then
                answer3 = b + c
                answer4 = answer3 - a
                Me.DueIn.Value = answer4
            Else

            End If
        End If

End Sub
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 09:03
Joined
May 21, 2018
Messages
8,463
This may run, but I am not sure about the logic. I would think this calculation needs component total hours for each component, but I believe your total hours is total hours for all components. That would not make sense. Also I do not see how you are tracking actual hours when the service was performed you seem to only track a notional schedule.
If I have a car that needs an oil change every 5,000 miles then my original plan is for service to happen at 5k, 10k, 15k, 20k. But If I do the first service early at 4,000 the next should show do at 9k not at the 10k original service plan. If I do the next service late at 12K then next should be due a at 17K not 15k. You seem to stick to the original interval regardless if any service performed.

Again I do not think you are doing any favors with your variables. Variables should help readability yours do the opposite. You took clear variable names like TotalHours and replaced with letters like A. Then you have unnecessary variables such as answer... answer4 that really do not do a
anything.

Here is the same code as yours simplified
Code:
Private Sub Form_Current()
       If Me.TotalHours< Me.ServiceInterval Then
             Me.DueIn.Value = Me.ServiceInterval - Me.TotalHours
        Else
          Me.Divider.Value = Me.TotalHours/ Me.ServiceInterval
          If TotalHours>  Me.ServiceHour Then
               me.DueIn = Me.ServiceInterval +  Me.ServiceHour - Me.TotalHours
          End If
        End If
End Sub

I find that very easy to read and determine what is going on. However you still need to check for ServiceInterval = null because this will fail
Code:
So if you want intermediat variables use something that is clear

Private Sub Form_Current()
        dim TotHrs as integer
        dim ServInt as integer
        dim ServHrs as integer
        
        TotHrs = NZ(TotHrs,0)
        ServInt = Nz(ServInt,0)
        ServHrs = nz(me.serviceHrs,0)
       if servHrs = 0 then exit Sub 
       If TotHrs< ServInt Then
             Me.DueIn.Value = ServInt - TotHrs
        Else
         Me.Divider.Value = TotHrs/ ServInt
         If TotalHours>  ServHrs Then
               me.DueIn = ServInt +  ServHrs - TotHrs
         End If
        End If
End Sub
 

Sam Summers

Registered User.
Local time
Today, 13:03
Joined
Sep 17, 2001
Messages
939
This may run, but I am not sure about the logic. I would think this calculation needs component total hours for each component, but I believe your total hours is total hours for all components. That would not make sense. Also I do not see how you are tracking actual hours when the service was performed you seem to only track a notional schedule.
If I have a car that needs an oil change every 5,000 miles then my original plan is for service to happen at 5k, 10k, 15k, 20k. But If I do the first service early at 4,000 the next should show do at 9k not at the 10k original service plan. If I do the next service late at 12K then next should be due a at 17K not 15k. You seem to stick to the original interval regardless if any service performed.

Again I do not think you are doing any favors with your variables. Variables should help readability yours do the opposite. You took clear variable names like TotalHours and replaced with letters like A. Then you have unnecessary variables such as answer... answer4 that really do not do a
anything.

Here is the same code as yours simplified
Code:
Private Sub Form_Current()
       If Me.TotalHours< Me.ServiceInterval Then
             Me.DueIn.Value = Me.ServiceInterval - Me.TotalHours
        Else
          Me.Divider.Value = Me.TotalHours/ Me.ServiceInterval
          If TotalHours>  Me.ServiceHour Then
               me.DueIn = Me.ServiceInterval +  Me.ServiceHour - Me.TotalHours
          End If
        End If
End Sub

I find that very easy to read and determine what is going on. However you still need to check for ServiceInterval = null because this will fail
Code:
So if you want intermediat variables use something that is clear

Private Sub Form_Current()
        dim TotHrs as integer
        dim ServInt as integer
        dim ServHrs as integer
       
        TotHrs = NZ(TotHrs,0)
        ServInt = Nz(ServInt,0)
        ServHrs = nz(me.serviceHrs,0)
       if servHrs = 0 then exit Sub
       If TotHrs< ServInt Then
             Me.DueIn.Value = ServInt - TotHrs
        Else
         Me.Divider.Value = TotHrs/ ServInt
         If TotalHours>  ServHrs Then
               me.DueIn = ServInt +  ServHrs - TotHrs
         End If
        End If
End Sub
Hi MajP, The form 'ViewServiceHistory' opens when the user selects the particular component so the hours and ServiceInterval is for the selected component.

The service intervals are fixed by law so are rigorously adhered to but that is up to the Boat Team.
It was what they asked me to set up?

I was so lost trying to get my head round the whole thing when i started that i was trying anything that seemed to work. Its all a bit above my ability but i'm trying to learn.
I will have a go with your code and see how i get on.
Thank you so much again!

I'll post back on here when it is properly solved
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 09:03
Joined
May 21, 2018
Messages
8,463
Hi MajP, The form 'ViewServiceHistory' opens when the user selects the particular component so the hours and ServiceInterval is for the selected component
Got it, you have to come in from the view vessel form. That makes more sense now.
The service intervals are fixed by law so are rigorously adhered to but that is up to the Boat Team
Is there a field that shows that they actually did the servicing? Recorded hours as I understand it logs how many hours run after each trip. Service Hours is a planned scheduled maintenance based on the service interval, but does not identify that the service was performed. Is that correct.
I will have a go with your code and see how i get on.
My code is the same as yours, I just did not use additional short variable names or intermediate variables for the calculations. Just reads different.
 

Sam Summers

Registered User.
Local time
Today, 13:03
Joined
Sep 17, 2001
Messages
939
Got it, you have to come in from the view vessel form. That makes more sense now.

Is there a field that shows that they actually did the servicing? Recorded hours as I understand it logs how many hours run after each trip. Service Hours is a planned scheduled maintenance based on the service interval, but does not identify that the service was performed. Is that correct.

My code is the same as yours, I just did not use additional short variable names or intermediate variables for the calculations. Just reads different.
Yes, sorry for not explaining better from the start.

And your second point is correct too. There is a separate form where the user logs the hours.

I will have a go with it right now
 

Sam Summers

Registered User.
Local time
Today, 13:03
Joined
Sep 17, 2001
Messages
939
Ok, that is it!

I just corrected the variable names and this works perfectly now so thank you all SO much!

Code:
        Dim TotHrs As Integer
        Dim ServInt As Integer
        Dim ServHrs As Integer
        
        TotHrs = Nz(Me.TotalHours, 0)
        ServInt = Nz(Me.ServiceInterval, 0)
        ServHrs = Nz(Me.ServiceHour, 0)
        
       If ServHrs = 0 Then Exit Sub
       If TotHrs < ServInt Then
             Me.DueIn.Value = ServInt - TotHrs
        Else
         Me.Divider.Value = TotHrs / ServInt
         If TotalHours > ServHrs Then
               Me.DueIn = ServInt + ServHrs - TotHrs
         End If
        End If
 

Users who are viewing this thread

Top Bottom