Add Conditional Column To Database
Hi Everyone.
First time poster, new to Visual Basic Express 2005, experienced with VBA.
I have 2 tables in an access database as shown below. I have created a vb express project with a link to the access database and a form with a datagridview showing table B.
What I would like to do is add a column to Table 2 either in design time or runtime. I want the new columns values to be the result of looking up the Limit column of table B and matching it to the Limits column of table A and adding the Current column to the interval column.
Hope that makes sense. Thanks in Advance.
Sam
Table A
| Limits | Current |
|---|
| AC Hours | 1000 |
| Engine 1 Hours | 1000 |
| NG 1 Cycles | 1356 |
| NF 1 Cycles | 1568 |
| Engine 2 Hours | 1000 |
| NG 2 Cycles | 1234 |
| NF 2 Cycles | 1789 |
| Hook Cycles | 189 |
| Hoist Cycles | 213 |
| Landings | 2300 |
Table B
| Limit ID | Comp ID | Aircraft | Date | Count | Event | Limit | Interval | Prior Count |
|---|
| 1 | 1 | ZK-HQQ |
| 0 | On Condition | AC Hours | 20000 | 0 |
| 2 | 2 | ZK-HQQ |
| 0 | Retire | Engine Hours | 20000 |
|
| 3 | 3 | ZK-HQQ |
| 0 | Retire | Ng Cycles | 20000 |
|
| 4 | 3 | ZK-HQQ |
| 0 | Retire | Landings | 120000 |
|
| 5 | 5 | ZK-HQQ |
| 0 | Retire | AC Hours | 20000 | 0 |
| 6 | 5 | ZK-HQQ |
| 0 | Retire | Landings | 120000 |
|
| 7 | 7 | ZK-HQQ |
| 0 | Retire | AC Hours | 20000 | 0 |
| 8 | 8 | ZK-HQQ |
| 0 | Retire | AC Hours | 20000 |
|
| 9 | 9 | ZK-HQQ |
| 0 | Overhaul | AC Hours | 2000 |
|
[13601 byte] By [
Reafidy] at [2008-1-10]
Nice tables !
If you're using the data designer I never found a way to change a table design after it was put in place but that was many years ago so I think design time is out which is one of many reasons why I won't use the data designer.
I have some other bad news for you. ADO does not have a way to add a column such that it is persistable in a database.
It's possible but I am not sure that the ADOX objects may use that but please be weary as they are COM Objects.
I believe you may be able to do this using sql statements. I have created entirely new tables with SQL.
What I said above relates to persisting these dataobjects. If there is no need to persist then, you can append all you want but it's my impression that this is not what you want to do.
This can be done thusly:
Dim a as new datacolumn
A.Datatype = system.type.Gettype("System.Integer") ' Case sensitve!!!!
A.ColumnName = "Bob"
Table.columns.add(a)
But I do not think there's anyway to persist this change without using ADOX or SQL.
Hi,
Thank you for the reply. 
Okay Ive carefully read your post a couple of times and Im thinking perhaps I didnt explain properly. I didnt use a data designer, I made the tables in MS access. I can change them to whatever I need. ie I can add a blank column if I need to.
The trouble for me is that I need a "formula" for this new column.
For example I managed to come up with a simple addition "formula" sorry I guess I should say "expression" (im new to non excel programs!) that add's to columns:
Code Snippet
Me.DB2DataSet.Tables("Limits").Columns("NewColumn").Expression = "[Prior Count] + [Interval]"
But this is not what I need. What I need is a expression that for each cell in this new column looks up the text in the "limit" column of "table B" and matches it to the "Limits" column of "Table A" and returns the corresponding value in the "current" column of "table A" which is then added to the value in the "interval" column of "table B". Arrrh what a mouthful I hope im making sense.
The results of the column I am trying to achieve would look like this:
21000
21000
21356
122300
etc..
Thank you very much for your help.
Sam
I was looking at your tables and i am guessing that you are trying to keep track of the hours on particular parts and perform maintenance or replace at certain intervals.
I don't know your system but it seems as though you could make it easier to keep track of individual parts and their hours if you were to break it up into several tables.
You have the same aircraft listed 9 times with different events, limits and intervals. After a while this is going to get real confusing to keep track of individual items.
Your master table could be the aircraft table for each individual aircraft
Then you would have a part or assembly table that would be a child of the aircraft table
this would give you the ability to keep track of specific parts for each aircraft
Then you have an hours table for each individual part or assembly
this will let you log individual hours for each trip or to make it easier you could just leave it with one record and update the hours as a total after each trip instead of dealing with a bunch of individual ones.
When you have them set up with a foreign key relationship then you can set it up to automatically filter the parts and hours based on which aircraft you select.
When you select aircraft with id - ZK-HQQ in the master table then it will show all the parts for that particular aircraft in the child part table and it will the show the hours for that particular part in the hours table.
Then you can run a report that will be based on a certain total hours for each part or assembly
Then you can check the total hours for each part or assembly and compare to the events and determine what needs to be done to the part or assembly.
I hope this makes sense
"
You have the same aircraft listed 9 times with different events, limits and intervals. After a while this is going to get real confusing to keep track of individual items."
The term for this is "normalization". This design is not normalized and the result will be exactly what JS06 described. Such databases are diffciult to support and to write code for. The are likely to be erroneous over time because one loses track of the locations of unnormalized data.
js06 wrote: |
| I was looking at your tables and i am guessing that you are trying to keep track of the hours on particular parts and perform maintenance or replace at certain intervals. | |
Yes Exactly!
I think I do actually have my tables setup similar to what you are saying. I just posted bad examples. I will post some actual examples from my tables below.
- I have a main table (no example shown) with a list of all the aircraft and its details ie manufacturer, type, model...
- I then have another table (Table A) which lists all the Limits that apply to the aircraft ie AC Hours, Engine Hours, Cycles, Landings...etc
- I then have another table (Table B) which lists all the components on the aircraft. This table contains all the component details it does not contain details of the limits because one component may have more than 1 limit assigned to it ie AC Hours and Landings.
- I have another table (Table C) which contains the limit details for each component.
All tables contain the aircraft rego ZK-HQQ. Tables B and C are linked by the "Comp ID".
The problem is I am trying to get the correct values in the "current", "remaining" and "due at" columns of table C. They need to look up the master limit table A to see where the aircraft is at in the "current column". The "remaining" and "due at" columns need to be calculated from this lookup column "current"
I have shown a few examples of the results i am looking for in the "current" "due at" and "remaining" columns.
Thanks you both for your ongoing help and patience. 
AC Master Limits (table A) | Limit Type | Aircraft | AC Serial No | Description | Current | Total | Calc Factor | Date Last Updated | TTCW | DateCW |
| AC Hours | ZK-HQQ | 4381 | Hourly Limit | 100 | 100 | Counts | 23/02/01 | 50 | 20/06/07 |
| Cycles | ZK-HQQ | 4381 | Cycle Limit | 120 | 120 | Counts | 27/02/01 | 89
| 20/06/07
|
| Engine 1 Hours | ZK-HQQ | 4381 | Hourly Limit | 100 | 100 | Counts | 27/02/01 | 46
| 30/05/06
|
| Months | ZK-HQQ | 4381 | Monthly | 0 | 0 | Months | 23/02/01 |
|
|
| Days | ZK-HQQ | 4381 | Days | 100 | 100 | Days | 13/09/01 |
|
|
| AC Hours | ZK-HZZ | 4234 | Hourly Limit
| 1000 | 1000 | Counts | 27/09/07 |
|
|
Component Details(Table B) | Aircraft | Tracking No | TT Installed | Sort Order | Assembly Name | Sub Assembly Name | Component | Part Number | Serial No | ATA | Comp ID | Date Installed |
| ZK-HQQ | 104 | 1500 | 1 | |
| Seat Belt | AS350-355678 | 3131 | 32-10 | 1 | 2/04/05 |
| ZK-HQQ | 105 | 1230 | 2 | |
| Tail Rotor Blade | AS350-239984 | 2134 | 42-10 | 2 | 3/08/06 |
| ZK-HQQ | 106 | 1230 | 3 | Aircraft
| Rotor Drive
| Main Drive Shaft | AS350-242332 | 3213 | 31-43 | 3 | 3/08/06 |
| ZK-HQQ | 107 | 1430 | 4 | Aicraft | Fuel | A/F Fuel Filter | AS350-234232 | 432 | 43-34 | 4 | 2/09/06 |
| ZK-HZZ | 108 | 3450 | 5 | Cockpit | Guages | Altimeter | AS355-323211 | 1422 | | 5 | 3/04/05 |
AC Limit Details(Table C) | ACLD ID | Aircraft | Limit Type | Life Limit | Event | Current | Prior Count | Transacted At | Remaining | Due At | Transacted Date | Comp ID |
| 1001 | ZK-HQQ | AC Hours | 2025 | Retire | 100 | 0 | 50 | 1975 | 2125 | 1/01/01 | 1 |
| 1002 | ZK-HQQ | Cycles | 3000 | Retire | 120 | 0 | 60 | 2940 | 3060 | 1/01/01 | 1 |
| 1003 | ZK-HQQ | Engine Hours 1 | 2025 | Retire | | 0 | 1146.00 |
|
| 1/01/01 | 1 |
| 1004 | ZK-HQQ | AC Hours | 4550 | Retire | | 926 | 1146 |
|
| 1/01/01 | 2 |
| 1005 | ZK-HQQ | Cycles | 6000 | Retire | | 2999 | 2998.00 |
|
| 27/02/01 | 2 |
| 1006 | Zk-HZZ | Engine Hours 1 | 4550 | Retire | | 926 | 1146.00 |
|
| 27/02/01 | 2 |
Ok, well i see basically what you are trying to do now.
You will have to bare with me because i have a little case of brain lock today. I have a lot on my mind because i am starting a new project and trying to think through setting up the database for it.
First let me say that i think i understand what you want as far as the calculations, however i think you could setup the whole database to work more efficiently for you. Let it do more of the work.
It still seems like the tables are setup a little more complex than they need to be.
I was thinking that it might help keep track of everything better if you were to break it up into more tables
Example:
Aircraft - master table (craft details and limits)
Assembly - child of aircraft
Sub Assembly - child of assembly
Component - child of sub assembly
And i see that you also want to keep track of the total hours and cycles of the craft itself
which i think you could do in the aircraft master table by using the limit types as your columns instead of a type for each row. And engine 1 would be a component of the aircraft wouldn't it?
What i am baseing all this on is the idea of keeping track of the time on all individual parts to either maintain or replace.
And i know this probably isn't exactly how it should be setup but i think this will give you more of an idea about normalizing it.
If you were to set it up similar to the above then if you had the tables on a single form then when you select a particular aircraft then it would automatically filter the assemblies for that aircraft and filter the sub assemblies for that assembly and also the components for that sub assembly.
If you were to select a different assembly then it would filter the sub assembly for that particular assembly and then filter the components for that sub assembly.
And if you were to select a different sub assembly then it would filter the components for that sub assembly.
It would all work in a chain.
Let me know what you think about all this and if it makes sense to you
It's late and i am tired so if it doesn't all make sense then let me know and i can get back to you
js06,
Thanks for your reply.
I currently have 2 datagridviews on my userform one which shows the component list table B. and when the users clicks on one of the components in that datagridview the second datagridview only show the limit details that apply to that component. I really like this for our particular situation it is very clear to the user. This is because one component might have a limit imposed by the manufacturer of 1000 AC hours and another limit of 3 Months and may be even another limit of 5000 Landing cycles just for that one component!
I dont have a need to filter by assembly or sub assembly yet. But I like your clever thinking and will definately think it over in fact I probably will use that idea. It would be good to like you say select an aircraft then have the 1st datagridview filtered to show only assemblies for that aircraft then filter again to show sub assemblies.
However I can still not see how that will help with my underlying problem. And that is getting the correct data for the calculations for the limits of each component. I only want to update the hours of the aircraft in the limit table I dont want to have to update the limits for each component individually.
Can you see away to do the calculations.
Thanks again for your help, its great, this is a big project for me and I am well aware of the complex nature and are more than prepared to put the work in. But I do appreciate all the help I can get!!
Once you get going on this i think it will get increasingly more difficult to have it automatically figure the time for each item if you don't set up the database correctly.
Either way what you are going to need is a set of loops that work together to look up the data in the limit table and match it to the current row of the compnent table.
Give me a little bit and i will give you some code to get you started on it. It won't be exactly what you need but it will give you a way to change it to make it work for you.
Ok i have some code for you.
This is based on the your first post where it shows tableA and tableB
How it works is to get the forst record from tableB and find the limit name and the interval
then it loops through the entire tableA untill it finds the match and then gets the current value
it adds the interval to the current value and then displays the total in the new column next to the record in tableB
It loops through every record in tableB repeating the same process
Basically
Get first record values in tableB
loop through tableA to find match then get value
add value and display
get next record and repeat again
etc...
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim totcol As New DataGridViewTextBoxColumn
totcol.HeaderText = "Total"
totcol.ValueType = System.Type.GetType(DbType.Int32)
Me.TableBDataGridView.Columns.Add(totcol)
Dim limitB As String = Nothing
Dim intervalB As Integer = 0
Dim limitA As String = Nothing
Dim currentA As Integer = 0
Dim total As Integer = 0
Dim tableBrow As Integer = 0
For Each rowB As DataRow In Me.DB2DataSet.TableB.Rows()
If Not TypeOf rowB("Limit") Is DBNull Then
limitB = rowB("Limit")
intervalB = rowB("Interval")
'MsgBox(r("Limit"))
End If
For Each rowA As DataRow In Me.DB2DataSet.TableA.Rows
If Not TypeOf rowA("Limits") Is DBNull Then
If rowA("Limits") = limitB Then
If Not TypeOf rowA("Current") Is DBNull Then
currentA = rowA("Current")
Exit For
End If
End If
End If
Next rowA
total = intervalB + currentA
Me.TableBDataGridView.Rows(tableBrow).Cells(9).Value = total
tableBrow = tableBrow + 1
Next rowB
End Sub
in this line Me.TableBDataGridView.Rows(tableBrow).Cells(9).Value = total
the cells(9) is the column index of the added total column
so if you have 5 columns and you add the new one - the index will be 5 because they start at 0
Now the problem you are going to have to face is if your database isn't setup properly it will never work correctly.
As you progress with this you will have to match up the aircraft, the assembly, sub assembly and then the component and then get the values.
I'm afraid though that as you move further into this project it will become very complex this is why you should set up your database correctly from the beginning. Once you get to a certain point you will realize that you may have to start over and redo the whole thing. But sometimes that may be unavoidable when working on a project like this. The whole idea is to keep everything in table groups to access the data easily and not have to find it in different places in the same table.
Let me know if you have any questions.
Good luck with it.
If you need me to i can send you the project i have setup with this code so you can see it work.
Ok excellent. So the solution is a lot of loops. I thought it would have been some kind of formula (thats my excel knowledge and inbuilt loathing of VBA loops getting in the way).
I understand all that code and can get it to work for my tables. I fully take onboard what you are saying about having the correct design. But I need to experiment a bit and find out the limitations before I can get a good design. I agree there will be times when I have to redo things due to bad design but I was expecting that.
One more question on the same issue. At the moment the code adjusts the values in the datagridview on the click of a button. What I would like is to calcuate and repopulate the values in the actual limits table when the program loads instead of in the datagridview. Then I can show the datagridview without having to loop each time its shown if Im switching between userforms. Is this possible?
Your ideas and suggestions have been very helpful!! - Thank You.
I'm not quite sure about populating the data in the table directly at the program load. I don't know how to do it with the loops. And i don't know how to modify the existing rows in the table directly.
If you are wanting to load the data and show it quickly when ready, another alternative might be to load the form and populate the datagridview at the program start and simply keep the form hidden untill you are ready for it. Instead of closing the form you can just hide it and then show it as needed.
Also, once you get the tables setup correctly, if you were to have the tables all on one form then you would not have to switch between forms. Or you can link the tables to work together on seperate forms and then you can just switch between the forms without closing them.
I would suggest starting a new thread for this question about populating the values directly in the table itself. This is just beyond my knowledge at the moment.
Okay No Problem. Youve been very helpful. I will carry on with the project and if I need too I will start a new thread.
Thank you everyone who has helped me.